重点是去重:
考虑一下去重问题,我使用了 O(n)O(n) 的判重方法:
设 stack 中最后一个值的位置为 last。如果 stack 为空,则 last = -1。
设当前正在处理的位置为 pos。
如果在 nums 的子区间 [last+1, pos) 中,存在和 nums[pos] 相同的值,则当前 nums[pos] 必须丢弃,不然会产生重复的子序列。
设现在 stack = [4, 6], pos = 4。
如果只检查是否递增的话,nums[4] = 7 是可以放入的,放入后 stack = [4, 6, 7]。
但是,当 stack = [4, 6] 时,last = 1,在 nums[last+1, 4) 中,还存在一个 nums[2] = 7。
这说明,在之前的递归中,已经构造出了 stack = [4, 6, 7] 这种情况。
所以,在 stack = [4, 6] 时,nums[4] = 7 应该丢弃。
当 stack = [4, 6, 7], pos = 4 时。
此时,last = 2
,pos = 4
,此时 nums[last+1, pos)
中,并没有其他的 7 了。
且放入后,stack
还是递增子序列,所以构造出了 stack = [4,6,7,7]
class Solution {
int[] pre = new int[15];
public List<List<Integer>> findSubsequences(int[] nums) {
for (int i = 0; i < nums.length; i++) {
pre[i] = -1;
for (int j = i - 1; j >= 0; j--) {
if (nums[j] == nums[i]) {
pre[i] = j;
break;
}
}
}
List<List<Integer>> anw = new ArrayList<>();
LinkedList<Integer> stack = new LinkedList<>();
dfs(nums, -1, 0, stack, anw);
return anw;
}
// 判重代码;
public boolean is_first(int last, int pos) {
return !(last < pre[pos] && pre[pos] < pos);
}
public void dfs(int[] nums, int last, int pos, LinkedList<Integer> stack, List<List<Integer>> anw) {
if(nums.length == pos) { return; } //到达末尾,直接范围吧
// 检查 nums[pos] 是否符合要求
if((stack.isEmpty() || nums[pos] >= stack.peekLast()) && is_first(last, pos)) {
stack.add(nums[pos]);
if(stack.size() >= 2) { //大于 2 了,那就放进去吧
anw.add(new ArrayList<>(stack));
}
dfs(nums, pos, pos+1, stack, anw); // 继续处理下一个。
stack.pollLast(); // 将当前放入这个吐出来。
}
dfs(nums, last, pos+1, stack, anw);
}
}