题目:​​https://leetcode.com/problems/increasing-subsequences/?tab=Description​

找出所有的长度大于等于2的递增序列。

思路:这里是找出所有的解。因此选择backtracking。要注意一点,关于去重。之前做过类似的,combinationsum那种,那个类型的题目是从集合中选元素,因此集合的顺序无关紧要,但是这里是序列,顺序是重要的,在序列中如何去重,用一个set。每一步,记录每一种选择,只尝试之前没有试过的选择。

举个例子,比如1,2,3,4,1,6。第一步,从0位置开始选择,可以选择1,第二步从1位置开始,可以选择6。这是一种方法,那么在第一步就把1加入了set。当遍历到4位置时,又遇到1,发现已经尝试过,跳过。因为如果不跳过,那么又会出现一个1,6的结果。重复。


所以对于backtracking而言,序列的话用一个set去重。但是如果是有序的,只要选择和上一个选择不同的即可。

代码:

public List<List<Integer>> findSubsequences(int[] nums) {
List<List<Integer>> r = new ArrayList<>();
if(nums == null || nums.length < 2) return r;
List<Integer> path = new ArrayList<>();
findSubsequencesSub(r, path, nums, 0);
return r;
}

private void findSubsequencesSub(List<List<Integer>> r, List<Integer> path, int[] nums, int start){
if(path.size() >= 2) r.add(new ArrayList<>(path));
Set<Integer> set = new HashSet<>();
for(int i = start; i < nums.length; i++){
if(!set.add(nums[i])) continue;
int last_cur = path.size() == 0?Integer.MIN_VALUE:path.get(path.size() - 1);
if(nums[i] >= last_cur){
path.add(nums[i]);
findSubsequencesSub(r, path, nums, i + 1);
path.remove(path.size() - 1);
}
}
}