置换、组和、子集问题总结
1.问题分析
https://leetcode.com/articles/subsets/
三个问题的解空间如上(看到这种问题真是脑瓜子嗡嗡的,好难)
其中子集问题,为2^n,因为每一个元素可能出现也可能不出现(原来是这样。)
一般的解决方法包括:递归、回溯、以及二进制操作(基于二进制位掩码和对应位掩码之间的映射的词典生成排列/组合/子集。)
文中提到,第三种方法最适合面试解法,它将问题简化为二进制数的生成,并且可以证明没有解是被遗漏的,并且时间复杂度最低,给出的答案是排好序的。
2.子集生成问题
递归解法https://leetcode.com/articles/subsets/这里讲解的很好。
在最后一种解法中,https://stackoverflow.com/questions/22832615/what-do-and-mean-in-python
python中的<<操作,原来是x*2^y啊,不是根据对应的二进制左移位数。
>>> 1<<1 2 >>> 1<<2 4 >>> 1<<3 8 >>> 1<<4 16
链接中给出来的:
public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> list = new ArrayList<>(); Arrays.sort(nums); backtrack(list, new ArrayList<>(), nums, 0); return list; } private void backtrack(List<List<Integer>> list , List<Integer> tempList, int [] nums, int start){ list.add(new ArrayList<>(tempList));//这里很厉害了 for(int i = start; i < nums.length; i++){ tempList.add(nums[i]); backtrack(list, tempList, nums, i + 1); tempList.remove(tempList.size() - 1); } }
所以套路是:回溯函数for循环,参数包括start和temp的list,函数内实现包括for循环,add,调用back函数,pop操作。