四数相加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 之外,这两个数字都不会以零开头. ...
随机推荐
- (工具) 交叉编译 gperftools及使用
交叉编译gperftools及使用 sudo apt-get install kcachegrind # 导出为 callgrind 格式时需要 sudo apt install doxygen-la ...
- 第2-4-9章 规则引擎Drools实战(2)-信用卡申请
目录 9.2 信用卡申请 9.2.1 计算规则 9.2.2 实现步骤 9.2 信用卡申请 全套代码及资料全部完整提供,点此处下载 本小节我们需要通过Drools规则引擎来根据规则进行申请人的合法性检查 ...
- 【Java SE进阶】Day10 缓冲流、转换流、序列化流 、打印流
一.缓冲流 1.概述 比普通流更强大的IO流,可以增加读写的效率 组成 缓冲输入流:BufferedInputStream.BufferedReader 缓冲输出流:BufferedOutputStr ...
- 项目完成小结 - Django-React-Docker-Swag部署配置
前言 最近有个项目到一段落,做个小结记录. 内容可能会多次补充,在博客上实时更新哈~ 如果是在公众号阅读这篇文章,可以点击「查看原文」访问最新版本~ 这个项目是前后端分离,后端为了快,依然用我的Dja ...
- UBOOT 启动流程
一.概述 uboot 的启动流程在网上有很多大佬记录,但是了对于像我这样的新手就有些困难了,而我也不做 uboot 相关的工作,所以没必去研究代码,这里我特意整理了一下,以流程图的形式展现代码执行的流 ...
- flutter系列之:如丝般顺滑的SliverAppBar
目录 简介 SliverAppBar详解 SliverAppBar的使用 总结 简介 对于一个APP来说,肯定会有一个AppBar,这个AppBar一般包含了APP的导航信息等.虽然我们可以用一个固定 ...
- js实现n秒内只能点击一次操作
<button @click="submit">5秒内只能点一次</button>
- python Flask 操作数据库(2)
单表操作 数据准备 from flask import Flask from flask_sqlalchemy import SQLAlchemy class Config: DEBUG = True ...
- JavaScript:操作符:算术运算符(加减乘除模幂)及其隐式转换数据类型
加法+ 减法- 乘法* 除法/ 模运算% 幂运算**,即a ** b求的是a的b次方 执行上述运算时,当两个操作数有非数字时,JS会隐式转换为数字,再进行运算: 一些特殊的非数字,会进行如下转换: t ...
- [机器学习] PCA主成分分析原理分析和Matlab实现方法
转载于http://blog.csdn.net/guyuealian/article/details/68487833 网上关于PCA(主成分分析)原理和分析的博客很多,本博客并不打算长篇大论推论PC ...