Leetcode 491 递增子序列
2023-12-13 13:12:38
题意理解:
输入: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.暴力回溯+剪枝优化
?回溯算法三个常见步骤:
? ? ? ? 确定返回值和参数列表
? ? ? ? 确定终止条件:集合中所有元素遍历完,即startIndex>nums.size
? ? ? ? 确定单层逻辑:使用uset来记录当前层用过的值。
注意: 子集递增,单不是严格递增,所以允许重复值存在。
? ? ? ? ? ? 剪枝: 当前层当前树枝的重复值要剪枝。
? ? ? ? ? ? ? ? ? ? ? ? 递减子序列要剪枝。
List<List<Integer>> result=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> 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(startIndex>=nums.length) return;//可以省略,因为startIndex>=nums.length,下面循环不会进入
//记录当前树枝当前层用过的值
Set<Integer> uset=new HashSet<>();
for(int i=startIndex;i<nums.length;i++){
if(uset.contains(nums[i])){//当前树枝当前层树枝重复则剪枝
continue;
}
if(path.size()!=0&&nums[i]< path.getLast()) continue;//递减时剪枝
uset.add(nums[i]);
path.add(nums[i]);
backtracking(nums,i+1);
path.removeLast();
}
}
2.分析
时间复杂度:O()
空间复杂度:O(n)
文章来源:https://blog.csdn.net/lt_BeiMo/article/details/134966005
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!