思路
正常子集、组合、集合都会想到回溯的方法。也就是逐层列举(类似冒泡的遍历形式 多层 for i=j)。 还有一种我们可以从用例看出规律,即每一次添加新的元素nums[i],所造成原有结果集增加的集合为:(集合i-1) + (集合i-1的每个数组加上新元素nums[i])。如: nums[i]=1 : {空集} , {空集,1} 即: [] , [1]
nums[i]=2 : [] , [1] ,[2] ,[1,2]
nums[i]=3 : [] , [1] ,[2] ,[1,2] , [3], [1,3] ,[2,3] ,[1,2,3] 加上后:
有点动态规划的味道: dp[i] = dp[i-1] , dp[i-1]每个元素加nums[i]
找规律
这里注意ArrayList不能边增大长度边<res.length,因为边界值和下标在变化。(又是一个JAVA面试题)
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
res.add(new ArrayList<>());
for (int i = 0; i < nums.length; i++) {
int tmpSize = res.size();
for (int j = 0; j < tmpSize; j++) {
List list = new ArrayList(res.get(j));
list.add(nums[i]);
res.add(new ArrayList(list));
}
}
return res;
}
时间 0 ms 击败 100% 内存 41.7 MB 击败 30.31%
回溯
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
// Arrays.sort(nums);
backtrack(new ArrayList() , 0 , nums);
return res;
}
public void backtrack(List temp , int index , int[] nums){
res.add(new ArrayList<>(temp));
if (index == nums.length){
return ;
}
for (int i = index; i < nums.length; i++) {
temp.add(nums[i]);
backtrack(temp , i+1 , nums);
temp.remove(temp.size()-1);
}
}
}