力扣90——子集 II
原题
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
原题url:https://leetcode-cn.com/problems/subsets-ii/
解题
递归
这道题,针对已经刷了不少题目的我们而言,应该第一想到的就是递归
了,从第1个数开始,每次遍历1个数,如果和之前的数相同则跳过,然后以下一个数为起点,继续遍历。让我们来看看代码:
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
// 从小到大排序
Arrays.sort(nums);
// 最终结果
List<List<Integer>> result = new LinkedList<>();
result.add(new LinkedList<>());
// 回溯
dfs(0, nums, new Stack<>(), result);
return result;
}
public void dfs(int index, int[] nums, Stack<Integer> stack, List<List<Integer>> result) {
if (index >= nums.length) {
return;
}
for (int i = index; i < nums.length; i++) {
// 在这一次总的查找中,如果当前节点和上一个节点相同,则跳过
if (i > index && nums[i] == nums[i - 1]) {
continue;
}
// 添加该数
stack.push(nums[i]);
// 作为一种情况,放进结果中
result.add(new LinkedList<>(stack));
// 继续回溯
dfs(i + 1, nums, stack, result);
// 回退
stack.pop();
}
}
}
提交OK,执行用时:2 ms
,内存消耗:36.5 MB
,但执行用时只战胜40.16%
,那就来优化一下。
优化
看了第一眼,我真的不知道该如何优化。我先是想到将递归改成迭代,但感觉并没有从时间上做出优化,不过还是给大家看一下:
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
if (nums == null || nums.length == 0) {
return new LinkedList<>();
}
// 从小到大排序
Arrays.sort(nums);
// 最终结果
List<List<Integer>> result = new ArrayList<>(1 << nums.length);
result.add(0, new LinkedList<>());
// 上一步新解的开始下标
int newStartIndex = 1;
// 遍历添加
for (int i = 0; i < nums.length; i++) {
int j = 0;
// 和上一个数字相同,则只针对上一步的新解增加
if (i > 0 && nums[i] == nums[i - 1]) {
j = newStartIndex;
}
int length = result.size();
newStartIndex = length;
for (;j < length; j++) {
List<Integer> tempList = result.get(j);
List<Integer> newList = new LinkedList<>(tempList);
newList.add(nums[i]);
result.add(newList);
}
}
return result;
}
}
提交之后,果然不出所料,和之前一样,那就再让我们想想。
还记得在之前文章中曾经说过,new LinkedList<>(Collection<? extends E> c)
其内部依旧是遍历,很耗性能。因此我专门看了一下new ArrayList<>(Collection<? extends E> c)
,其内部最终会调用Systemp.arraycopy
。让我们再试一次:
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
// 从小到大排序
Arrays.sort(nums);
// 最终结果
List<List<Integer>> result = new LinkedList<>();
result.add(new ArrayList<>());
// 回溯
dfs(0, nums, new Stack<>(), result);
return result;
}
public void dfs(int index, int[] nums, Stack<Integer> stack, List<List<Integer>> result) {
if (index >= nums.length) {
return;
}
for (int i = index; i < nums.length; i++) {
// 在这一次总的查找中,如果当前节点和上一个节点相同,则跳过
if (i > index && nums[i] == nums[i - 1]) {
continue;
}
// 添加该数
stack.push(nums[i]);
// 作为一种情况,放进结果中
result.add(new ArrayList<>(stack));
// 继续回溯
dfs(i + 1, nums, stack, result);
// 回退
stack.pop();
}
}
}
提交之后,果然OK了,执行用时:1 ms
,战胜100%
的 java 提交记录。
我这里再说明一下,LinkedList 的遍历拷贝,每个元素都需要重新计算内存位置,而 ArrayList 的拷贝,可以直接一次性申请一大片空间,写入和遍历的速度会更快。
总结
以上就是这道题目我的解答过程了,不知道大家是否理解了。这道题目只要利用递归就可以解决了,但优化的时候,需要注意数据结构(是不是我之前用一些的 LinkedList 换成 ArrayList 会效果更好呢)。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
公众号:健程之道
力扣90——子集 II的更多相关文章
- 90. 子集 II
90. 子集 II 题意 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2]输出:[ [2], [1], ...
- Leetcode之回溯法专题-90. 子集 II(Subsets II)
Leetcode之回溯法专题-90. 子集 II(Subsets II) 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入 ...
- Java实现 LeetCode 90 子集 II(二)
90. 子集 II 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [ ...
- [leetcode] 90. 子集 II.md
90. 子集 II 78. 子集题的扩展,其中的元素可能会出现重复了 我们仍沿用78题的代码,稍作改动即可: 此时需要对nums先排个序,方便我们后面跳过选取相同的子集. 跳过选取相同的子集.当选取完 ...
- 刷题-力扣-213. 打家劫舍 II
213. 打家劫舍 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/house-robber-ii/ 著作权归领扣网络所有.商业 ...
- leetcode刷题-90子集 II
题目 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2]输出:[ [2], [1], [1,2,2], [ ...
- leetcode 90. 子集 II JAVA
题目: 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [1,2,2] ...
- Leetcode 90. 子集 II
地址 https://leetcode-cn.com/problems/subsets-ii/ 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重 ...
- LeetCode 90. 子集 II(Subsets II)
题目描述 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: [1,2,2] 输出: [ [2], [1], [1,2,2 ...
随机推荐
- hdu 1054 【树形dp】
http://acm.hdu.edu.cn/showproblem.php?pid=1054 给定一棵树,点能看住与其相连的边,问最少需要选定多少个点看住所有的边. 定义dp[maxn][2],dp[ ...
- ArcGIS下如何提取研究区域
举个例子,如果我用“按位置选择工具”从shitrt图层中提取普查小区在count6中的部分,并将结果输出为shapefile文件cnty6trt,可以这么做: 就OK了
- JAVA内存dump
# 注意点: # 项目运行的用户 # 使用的jdk版本下的jstack去查看 /opt/jdk1..0_191/bin/jmap -dump:format=b,file=/webser/www/`da ...
- 一个 PHP 面试题
一个 PHP 面试题 $i = 0; $j =1; if ($i = 5 || ($j =6)) {echo $i,$j++;} 拿来当面试题不错. 实际并不会这样用,但这个题可以考基础.
- *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<_UIFeedbackParameters 0x1d4442e50> setNilValueForKey]: could not set nil as the value for the key rate.'
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<_UIFeedbac ...
- AspNetPager 样式
使用方法: 1.引入样式表. 将 想要使用的样式表加入到本页面<style type="text/css"></style>标记中,或者新建一个css文件如 ...
- Ext.FormPanel-----FieldSet的用法
Ext.form.FieldSet的常用配置项: 1.checkboxToggle : Mixed True表示在lengend标签之前fieldset的范围内渲染一个checkbox,或者送入一个D ...
- Mysql错误:#1054 - Unknown column 'id' in 'field list' 解决办法
第一次用mysql,在插入数据时,竟然报这样的错误, #1054 - Unknown column 'id' in 'field list'
- Keras框架下的保存模型和加载模型
在Keras框架下训练深度学习模型时,一般思路是在训练环境下训练出模型,然后拿训练好的模型(即保存模型相应信息的文件)到生产环境下去部署.在训练过程中我们可能会遇到以下情况: 需要运行很长时间的程序在 ...
- Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage)
解决方案是删除 pom.xml配置的问题 <build> <plugins> <plugin> <groupId>org.springframework ...