务川网站建设,广告投放网站,本地wordpress后台,网站设计的评估题意理解#xff1a; 输入#xff1a;nums [4,6,7,7]
输出#xff1a;[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]] 这里不止要找一个子序列#xff0c;还要元素保证其在原来的集合中的前后顺序#xff0c;且应为增序。 为保证一个增序序列#xff0c;… 题意理解 输入nums [4,6,7,7]
输出[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]] 这里不止要找一个子序列还要元素保证其在原来的集合中的前后顺序且应为增序。 为保证一个增序序列所以题目也要求子集大小最小为2. 要注意集合中的元素有重复需要去重操作。——这就是这道题的难点。 解题思路 涉及子集问题一般可以用回溯的方法来进行解决。 回溯的解决方案通常可以抽象为一棵树。可以画一幅画来理解 紫色的部分即为需要剪枝去重的地方所以我们需要一个设置uset来记录当前层用过的元素当当前层有重复元素出现时需要进行剪枝操作。 1.暴力回溯剪枝优化 回溯算法三个常见步骤 确定返回值和参数列表 确定终止条件集合中所有元素遍历完即startIndexnums.size 确定单层逻辑使用uset来记录当前层用过的值。
注意 子集递增单不是严格递增所以允许重复值存在。 剪枝 当前层当前树枝的重复值要剪枝。 递减子序列要剪枝。
ListListInteger resultnew ArrayList();LinkedListInteger pathnew LinkedList();public ListListInteger findSubsequences(int[] nums) {backtracking(nums,0);return result;}public void backtracking(int[] nums,int startIndex){//结果收集if(path.size()2) result.add(new ArrayList(path));if(startIndexnums.length) return;//可以省略因为startIndexnums.length下面循环不会进入//记录当前树枝当前层用过的值SetInteger usetnew HashSet();for(int istartIndex;inums.length;i){if(uset.contains(nums[i])){//当前树枝当前层树枝重复则剪枝continue;}if(path.size()!0nums[i] path.getLast()) continue;//递减时剪枝uset.add(nums[i]);path.add(nums[i]);backtracking(nums,i1);path.removeLast();}}
2.分析 时间复杂度O() 空间复杂度O(n)