Leetcode 40组合总数(回溯)Ⅱ41缺失的第一个正数42接雨水
维护公众号:
bigsai
,回复进群加入打卡,回复bigsai
分享一些学习资源!
上周第一次 LeetCode 36有效的数独&37解数独(八皇后问题)
上周第二次 LeetCode 38外观数列&39组合总和
昨日打卡 Leetcode 40组合总数(回溯)Ⅱ&41缺失的第一个正数
目录
- 组合总数(回溯)
- 缺失的第一个正数
- 接雨水
- 结语
组合总数(回溯)
题目描述:
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
andidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[[1, 7],[1, 2, 5],[2, 6],[1, 1, 6]
]
示例 2:输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[[1,2,2],[5]
]
分析,这题和组合总数Ⅰ有所不同,上一题是任意一个数可以出现任意多次并且形式上没有重复的。
但是这题有重复的但是每个数只能使用一次。如果按照上一题的分析思路就是就是回溯的过程需要进行下一个,并且需要一个哈希对结果去重。
但是我们都知道哈希虽然效率还行但是频繁的判断很影响算法的效率,有什么好的方法去解决?我们在回溯算法上进行合理剪枝。用一个策略去重。
首先对于这个序列,我们先进行排序,排完序之后我们进行一下分析:
怕重复?无非是怕以下的这种情况嘛:
而我们在实际处理的时候,同一个元素如果用多次,只能从第一个元素顺序使用而不能跳跃使用。
在具体的处理方式我,刚开始我用了比较笨的方法:每次找到这个元素找到它相同的区间。然后遍历这个区间排列所有个数(从左向右),同时判断满足条件(数值总和不超出的情况下),递归下一个节点到下一个数值的编号上。当然不使用该元素在最后特殊进行一次dfs即可。
List<Integer> list = new ArrayList<Integer>();// list用来回溯过程中储存元素
List<List<Integer>> val = new ArrayList<List<Integer>>();// 结果public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);dfs(0, candidates, target);return val;
}/** index 表示当前编号 count 表示当前数值的和*/
private void dfs(int index, int[] candidates, int target) {// System.out.println(list.toString());if (target == 0) {val.add((new ArrayList<Integer>(list)));return;} else if (index == candidates.length) {return;} else {int r = index;while (r < candidates.length && candidates[index] == candidates[r]) {r++;}int i;for (i = index; i < r; i++) {target -= candidates[i];list.add(candidates[i]);if (target>=0) {dfs(r, candidates, target);} else {//没有执行dfs但是数值需要恢复 因为i还是变了target += candidates[index];list.remove(list.size() - 1);break;}}for (; i > index; i--) {target += candidates[index];list.remove(list.size() - 1);}dfs(r, candidates, target);// 不使用该元素的}
}
算法 4ms不太行,因为提前计算出右r的位置的时候进行一部分重复量挺大的运算。参考了别人的代码,才发现具体处理上可以这么处理:
遍历时候正常遍历,只不过进行遍历的时候判断如果该元素不是这次首元素的话和前面元素相等那么直接跳过。否则正常进行dfs。这样就可以过滤掉所有重复情况:
最终ac的代码为:
List<Integer> list = new ArrayList<Integer>();// list用来回溯过程中储存元素
List<List<Integer>> val = new ArrayList<List<Integer>>();// 结果public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);dfs(0, candidates, target);return val;
}/** index 表示当前编号 count 表示当前数值的和*/
private void dfs(int index, int[] candidates, int target) {if (target == 0) {val.add((new ArrayList<Integer>(list)));return;}for(int i=index;i<candidates.length;i++){if(target-candidates[i]<0)break;if(i!=index&&candidates[i]==candidates[i-1])continue;list.add(candidates[i]);dfs(i+1, candidates, target-candidates[i]);list.remove(list.size()-1);}
}
缺失的第一个正数
对于这题,如果不要求其他的,给一个数组空间的话,可以使用数组作为索引,直接干0ms:
public int firstMissingPositive(int[] nums) {int time[]=new int[nums.length+1];for(int i=0;i<nums.length;i++){if(nums[i]>0&&nums[i]<nums.length){time[i]++;}}for(int i=1;i<time.length;i++){if(time[i]==0)return i;}return nums.length;}
但问题是人家要求的是常数级别空间。还是没想出来忍不住看了下题解恍然大悟:
数组妙用。分析问题,求未出现的最小正数,也就是最理想的情况是1.否则就找个未出现的最小的。这题核心的想法是复用数组,我们只需标记这个位置的数字有没有出现过! 所以可以用负数表示。
按照以下三点分析,首先我们知道这个数组中可能有负数或者大于数组长度数值的数存在,我们第一次遍历要将这些数置为1,并且看看1是否存在。如果不存在直接返回1即可。
第二次遍历,将对应编号位置数改为负数(注意初始正负)。注意取值。
第三次遍历找到第个为正数的那个位置,返回编号加1.如果为正数说明这个数未出现。
具体ac代码为:
public int firstMissingPositive(int[] nums) {boolean jud =false;//第一轮循环,将无用的数字置为1 如果整个数列中没有1 那么将返回1for(int i=0;i<nums.length;i++){if(nums[i]<=1||nums[i]>nums.length){if(nums[i]==1)jud=true;nums[i]=1;}}if(!jud)return 1;//第二轮循环,所有数字现在目前的状态是1 - nums.length区间内for(int i=0;i<nums.length;i++){int index=Math.abs(nums[i])-1;//该位置对应的索引if(nums[index]>0) {nums[index]=-nums[index];}}for(int i=0;i<nums.length;i++){if(nums[i]>0)return i+1;}return nums.length+1;}
接雨水
题目分析
遇到这种题总有那么种似曾分析的感觉,我来谈谈如何分析这道题。
我的个人思路来说,我觉得这道题的核心就是看看能不能找到中间最高的元素。
找到这个最高点后:
- 左右进行相等操作,从左来看,需要一个
l
和lteam
,让lteam往右试探. - 试探途中如果height[lteam]<height[l],继续前进,后面一定会有更大的。
- 试探途中如果height[lteam]>height[l],计算途中雨点和,然后l赋值为lteam,继续试探。
而同样右侧是进行一个从右往左的操作。
不过再具体实现上,本人初次只考虑从左往右然后遇到没有比它更大的找个次大的计算雨水。然后重新进行。具体代码为:
public int trap(int[] height) {int l=0,r=l+1;int count=0;int max=0,maxindex=0;while (l<height.length&&r<height.length) {if(height[r]>=height[l])//找到更大的靠山{for(int i=l;i<r;i++){count+=height[l]-height[i];}l=r;r++;max=0;maxindex=0;}else {//不大于if(height[r]>=max){max=height[r];maxindex=r;}r++;if(r==height.length){for(int i=l+1;i<maxindex;i++){count+=max-height[i];}l=maxindex;r=l+1;max=0;maxindex=0;}}}return count;}
效果一般般因为遇到逆序形的会O(n2)算法。最好情况O(n)。
而换一种O(n)的写法之后,找到最大后右侧往左一次即可:
public int trap(int[] height) {int l=0,r=l+1;
int count=0;while (l<height.length&&r<height.length) {if(height[r]>=height[l])//找到更大的靠山{for(int i=l;i<r;i++){count+=height[l]-height[i];}l=r;r=l+1;}else {//不大于r++;if(r==height.length)//说明当前的left已经是天底下最大的值了{int max=0;for(int i=r-1;i>l;i--){if(height[i]>max){max=height[i];}else{count+=max-height[i];}}l=r;}}
}
return count;
效果还行:
结语
原创不易,bigsai请你帮两件事帮忙一下:
star支持一下, 您的肯定是我在平台创作的源源动力。
微信搜索「bigsai」,关注我的公众号,不仅免费送你电子书,我还会第一时间在公众号分享知识技术。加我还可拉你进力扣打卡群一起打卡LeetCode。
记得关注、咱们下次再见!
Leetcode 40组合总数(回溯)Ⅱ41缺失的第一个正数42接雨水相关推荐
- Leetcode算法Java全解答--41. 缺失的第一个正数
Leetcode算法Java全解答–41. 缺失的第一个正数 文章目录 Leetcode算法Java全解答--41. 缺失的第一个正数 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 ...
- Java实现 LeetCode 41 缺失的第一个正数
41. 缺失的第一个正数 给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0] 输出: 3 示例 2: 输入: [3,4,-1,1] 输出: 2 示例 3: ...
- 41. 缺失的第一个正数 golang
41. 缺失的第一个正数 给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0] 输出: 3 示例 2: 输入: [3,4,-1,1] 输出: 2 示例 3 ...
- 努力前端【LeetCode-10】448. 找到所有数组中消失的数字 442. 数组中重复的数据(中等) 41. 缺失的第一个正数(困难) [鸽笼原理,数组,Map,类似No.645]
文章目录 题目描述-448 一.哈希Map 二.空间复杂度的优化--鸽笼原理 三.总结 题目描述-442 一.还是hashMap 二.继续鸽笼原理 题目描述-41 一.基础方案 二.数组模拟Map 题 ...
- LeetCode 41. 缺失的第一个正数
文章目录 1. 题目信息 2. 思路 3. 代码 1. 题目信息 给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1:输入: [1,2,0] 输出: 3 示例 2:输入: [3,4, ...
- 【LeetCode笔记】41. 缺失的第一个正数(Java、哈希)
文章目录 题目描述 思路 & 代码 题目描述 难点在于时空复杂度的要求 想出最优方法,需要认真理解题目. 思路 & 代码 做法:建立一个逻辑上的哈希表,令 nums[i] = i + ...
- leetcode —— 41. 缺失的第一个正数
给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0] 输出: 3 解题思路: 判断数组中是否存在1,如果没有1则直接返回1,结束: 如果数组长度为1,同时 ...
- LeetCode 41. 缺失的第一个正数 First Missing Positive
给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0] 输出: 3 示例 2: 输入: [3,4,-1,1] 输出: 2 示例 3: 输入: [7,8,9,11 ...
- 41,缺失的第一个正数
解题思路 一,暴力肯定不可取,时间要O(n^2) 二,sort一遍也不行,空间要O(n) 三,时间要O(n),空间常数,只能找方法. 可以想到,如果每个数字刚好对应那个 空间地址(nums[i]==i ...
最新文章
- 给GAN一句描述,它就能按要求画画,微软CVPR新研究 | 附PyTorch代码
- HTTP Status 405 - JSPs only permit GET POST or HEAD问题的分析和解决办法
- Java黑皮书课后题第10章:*10.22(实现String类)Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString1)
- 大唐波斯将军 机器人_你的工作会被机器人取代吗?
作者:大唐波斯将军2015-04-08 09:34...
- 前端技术之_CSS详解第五天
- 《史无前例!编程语言python斩获最有发展第一与排行榜第三!》深入 Python 流程控制
- 文本框仅可接收decimal
- 转载-聊一聊深度学习的activation function
- 软件架构师的12项修炼--软技能篇
- 【转】LDA-linear discriminant analysis
- [javax.validation]验证
- TP-LINK WR841N V8刷OpenWRT
- Atitit.创业之uke团队规划策划 v9
- 神经网络之智能科学与技术专业
- 视频教程-C++ 编写WebService服务实战-C/C++
- python数学建模|综合评价方法
- 数据库系统常用的数据模型
- vc sp5 补丁下载地址
- vs2003远程调试总结
- html表格数据填充,bootstrap table.js动态填充单元格数据的多种方法