置换、组和、子集问题总结

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

https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)

链接中给出来的:

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操作。

原文地址:https://www.cnblogs.com/BlueBlueSea/p/12285737.html