四数相加II & 赎金信 & 三数之和 & 四数之和
一、四数相加Ⅱ
1.方法概述
- 首先定义一个map,key放a和b两数之和,value 放a和b两数之和出现的次数。遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。定义int变量count,用来统计 a+b+c+d = 0 出现的次数。在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。最后返回统计值 count 就可以了。
2、具体实现
Java实现
点击查看代码
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap<>();
int tmp;
int ret = 0;
for(int i:nums1){
for(int j:nums2){
tmp = i+j;
if(map.containsKey(tmp)){
map.put(tmp,map.get(tmp)+1);
}else{
map.put(tmp,1);
}
}
}
for(int i:nums3){
for(int j:nums4){
tmp = i+j;
if(map.containsKey(0-tmp)){
ret += map.get(0-tmp);
}
}
}
return ret;
}
}
3.要点总结
- 因为本题即涉及到目标值又涉及到次数的统计,可以考虑使用map来解决。map的key来存放值,value来存放出现的次数。
- 本题是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况。
- 两两数组匹配寻找在时间效率上更优。
二、救赎金
1.方法概述
- 本题判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成,首先创建一个大小为26的数组来记录,字母出现的位置和次数。使用增强for和toCharArray()来遍历字符串,第一个字符串字母-'a'存入数组所对应的下标对应值+1用来记录出现次数.第二个字符串字母-'a'对应的下标对应值-1。最后遍历数组中是否含有<0的情况即可。
2.具体实现
Java实现
点击查看代码
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
for(char c : magazine.toCharArray()){
arr[c-'a'] +=1;
}
for(char c:ransomNote.toCharArray()){
arr[c-'a'] -=1;
}
for(int i:arr){
if(i<0){
return false;
}
}
return true;
}
}
3.要点总结
- 因为题目所只有小写字母,那可以采用空间换取时间的哈希策略,用一个长度为26的数组还记录magazine里字母出现的次数。然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。
- toCharArray() 方法将字符串转换为字符数组。
三、三数之和
1.方法概述
- 引用解法。首先将给定整数数组进行排序,使其从小到大依次排列。然后最外层使用for循环,i从下标0开始,同时定义一个位置在i+1上的left下标,定义一个在数组末尾位置上的right下标。在数组中查找a(nums[i])+b(nums[left])+c(nums[right])=0。当a+b+c>0,说明三数之和大了,需要right下标向左移动,如果a+b+c<0则需要left向右移动。当a+b+c=0时将元素值存放到二维数组ret中。因为该题需要不重复的三元组(组里面的元素可以重复),接下来就是a,b,c的去重操作。首先是a的去重,因为首先是在第一个元素确定的情况下查找的剩下两个元素,如果当第一个元素重复时就说明这样的情况已近存在,需要去重。同理接下来就是b,c的去重。最后返回ret。
2.具体实现
Java实现
点击查看代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0;i<nums.length;i++){
if(nums[i] > 0){
return ret;
}
if(i>0 && nums[i] == nums[i-1]){
continue;
}
int left = i+1;
int right = nums.length-1;
while(right>left){
int sum = nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{
ret.add(Arrays.asList(nums[i],nums[left],nums[right]));
while(right>left && nums[right] == nums[right-1]){
right--;
}
while(right > left && nums[left] == nums[left+1]){
left++;
}
right--;
left++;
}
}
}
return ret;
}
}
3.要点总结
- 首先将数组进行排序,本题原数组元素和下标对本题的解决无影响,可以先进行排序,方便后面的查找遍历以及去重操作。
- 本题的难点在于三元组不重复,在查找目标元素时需要去重操作。去重操作的核心就是判断三元组的第一个元素是否在它之前出现过,如果出现过,则证明该元素已近遍历过,在遍历同样的元素,必定导致重复三元组的出现。
- 在for循环这层遍历中,left和right需要不停的遍历寻找匹配元素,同时也需要去重操作,去重的思想和a的去重思想是一致。判断下一个元素是否和上一个出现元素相同,不同点是一个是从i+1下标开始遍历,另一个是从数组末端下标开始遍历。如果大了,说明right需要左移,如果小了,说明left需要右移,否则存入到二维数组中去,直到相遇,停止while层循环(因为题设要求满足i != left != right),进入下一次for循环。
- 还有一个关键点是b,c的去重要建立在存在一个三元组之后,否则就都会被去掉。
- 当b,c去重以后指针实际指向与第二位b(与第三位c)相同的数,因此指针需要移动指向不同的数,因此还需要left++,right--;
四、四数之和
1.方法概述
- 总体思想和三数之和一样,只是需要在最外层再套一个for循环来确定一个元素。
2.具体实现
Java实现
点击查看代码
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ret = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0;i < nums.length;i++){
if(nums[i]>0 && nums[i]>target){
return ret;
}
if(i>0 && nums[i-1] == nums[i]){
continue;
}
for(int j = i+1;j<nums.length;j++){
if(j > i+1 && nums[j-1] == nums[j]){
continue;
}
int left = j+1;
int right = nums.length-1;
while(left<right){
long sum = (long)nums[i]+nums[j]+nums[left]+nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
ret.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
while(left < right && nums[right] == nums[right-1]){
right--;
}
while(left < right && nums[left] == nums[left+1]){
left++;
}
left++;
right--;
}
}
}
}
return ret;
}
}
3.要点总结
- 不要判断nums[k] > target 就返回了,三数之和 可以通过 nums[i] > 0 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4, -3, -2, -1],target是-10,不能因为-4 > -10而跳过。但是我们依旧可以去做剪枝,逻辑变成nums[i] > target && (nums[i] >=0 || target >= 0)就可以了。
- 因为只要 nums[k] + nums[i] > target,那么 nums[i] 后面的数都是正数的话,就一定不符合条件了。
四数相加II & 赎金信 & 三数之和 & 四数之和的更多相关文章
- 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和
第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...
- 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和
[算法训练营day7]LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和 LeetCode454. 四数相加I ...
- Leetcode 454.四数相加II
四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单 ...
- Java实现 LeetCode 454 四数相加 II
454. 四数相加 II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...
- 【哈希表】leetcode454——四数相加II
编号454:四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...
- LeetCode 445. 两数相加 II(Add Two Numbers II)
445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个 ...
- Java实现 LeetCode 445 两数相加 II
445. 两数相加 II 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会 ...
- LeetCode454. 四数相加 II
题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 分析 关键是如何想到用 ...
- LeetCode 445——两数相加 II
1. 题目 2. 解答 2.1 方法一 在 LeetCode 206--反转链表 和 LeetCode 2--两数相加 的基础上,先对两个链表进行反转,然后求出和后再进行反转即可. /** * Def ...
- Leetcode 445. 两数相加 II
1.题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. ...
随机推荐
- 链表实现-回文palindrome判断
1.数字回文判断(逆转,分离未位,砍掉个位,保存原来) s = s * 10 + a%10 a = a/10 2.字符串判断回文 package main //思路: 开发一个栈来来存放链表的上半段f ...
- yum的$releaser与$basearch
最近配置centos 的yum 源时,想要配置一个通配的yum源,注意到发行的网络yum源的url地址中通常有两个变量 https://vault.centos.org/$releaser/cloud ...
- PEP8语法规范解释说明
PEP8规范解析 内容概要: 1.PEP8规范是什么? 2.PEP8相关内容 1.PEP8规范是什么 PEP是Python Enhancement Proposal的缩写,翻译为:"Pyth ...
- Karmada跨集群优雅故障迁移特性解析
摘要:在 Karmada 最新版本 v1.3中,跨集群故障迁移特性支持优雅故障迁移,确保迁移过程足够平滑. 本文分享自华为云社区<Karmada跨集群优雅故障迁移特性解析>,作者:Karm ...
- day23 约束 & 锁 & 范式
考点: 乐观锁=>悲观锁=>锁 表与表的对应关系 一对一:学生与手机号,一个学生对一个手机号 一对多:班级与学生,一个班级对应多个学生 多对一: 多对多:学生与科目,一个学生对应多个科目, ...
- 关键字break和continue
关键字:break 和continue提供了另一种控制循环的方式. break 是直接退出循环体 如: continue 是退出当前循环迭代 如: 需要注意的是:使用过多的break和continu ...
- 使用docker中的MySQL
简言 好久没写文章了,今天分享一篇将mysql移到docker容器.大家都是程序员,如何安装docker我就不说了. 1. 安装.启动mysql镜像 首先使用 docker search mysql ...
- Django路由层之路由分发 名称空间 虚拟环境 视图层之三板斧 JsonRsponse对象 request对象获取文件 FBV与CBV CBV源码剖析 模板层
目录 路由层之路由分发 路由层之名称空间 方式1:名称空间 方式2:别名不冲突即可 虚拟环境 pycharm创建虚拟环境 命令行形式创建虚拟环境 视图层之三板斧 HttpRsponse render ...
- global与nonlocal、函数名用法、闭包函数、装饰器
今日内容回顾 目录 今日内容回顾 global与nonlocal 函数名的多种用法 闭包函数 装饰器简介 装饰器推导流程 装饰器模板 装饰器语法糖 练习 global与nonlocal 函数名的多种用 ...
- 正则提取器和beanshell处理器组合,将提取的所有id拼接成字符串
1.添加正则表达式,提取所有id值 2.添加beanshell处理器将所有的id值拼接成字符串 方法一: int N = Integer.parseInt(vars.get("build_m ...