一、四数相加Ⅱ

454. 四数相加 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的情况。
  • 两两数组匹配寻找在时间效率上更优。

二、救赎金

383. 赎金信

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--;

四、四数之和

18. 四数之和

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 & 赎金信 & 三数之和 & 四数之和的更多相关文章

  1. 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和

    第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...

  2. 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和

    [算法训练营day7]LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和 LeetCode454. 四数相加I ...

  3. Leetcode 454.四数相加II

    四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单 ...

  4. Java实现 LeetCode 454 四数相加 II

    454. 四数相加 II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...

  5. 【哈希表】leetcode454——四数相加II

    编号454:四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...

  6. LeetCode 445. 两数相加 II(Add Two Numbers II)

    445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个 ...

  7. Java实现 LeetCode 445 两数相加 II

    445. 两数相加 II 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会 ...

  8. LeetCode454. 四数相加 II

    题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 分析 关键是如何想到用 ...

  9. LeetCode 445——两数相加 II

    1. 题目 2. 解答 2.1 方法一 在 LeetCode 206--反转链表 和 LeetCode 2--两数相加 的基础上,先对两个链表进行反转,然后求出和后再进行反转即可. /** * Def ...

  10. Leetcode 445. 两数相加 II

    1.题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. ...

随机推荐

  1. Atcoder补题计划

    11.17 AtCoder Regular Contest 151 知识点: A:简单题 B:计数,并查集 补题传送门

  2. OpenCV之C++经典案例

    四个案例实战 1.刀片缺陷检测 2.自定义对象检测 3.实时二维码检测 4.图像分割与色彩提取 1.刀片缺陷检测 问题分析 解决思路 尝试二值图像分析 模板匹配技术 代码实现 #include < ...

  3. springboot接收前端传参的几种方式

    1.通过HttpServletRequest接收,常用于获取请求头参数以及Cookie,适用于GET 和 POST请求方式,以下两种方式: @GetMapping("/demo1" ...

  4. 在Windows模拟器中使用LVGL8.3

    引言 LVGL是一个跨平台.轻量级.易于移植的图形库.也因其支持大量特性和其易于裁剪,配置开关众多,且版本升级较快,不同版本之间存在一定的差异性,相关的使用教程有一定的滞后性,由于缺少最新版本的中文教 ...

  5. python-名称空间与作用域

    名称空间与作用域 (1)名称空间(namespaces) 用来存放名字的地方是对栈区的划分 有了名称空间,就可在栈区中放相同的名字 1.1.内置名称空间 存放的名字:是Python解释器内置的名字 & ...

  6. 5:Echarts数据可视化-多条曲线、多个子图、TreeMap类似盒图、树形图、热力图、词云

    〇.目标 本次实验主要基于Echarts的Python库实现高维数据.网络和层次化数据.时空数据和文本数据的可视化,掌握可视化的操作流程和相关库的使用. 一.绘制平行坐标系 平行坐标是信息可视化的一种 ...

  7. SQL语句筛选/查询

    目录 SQL语句查询关键词 查询关键字之where筛选 查询关键字之分组 group by Group_concat 方法 查询关键字之having过滤 查询关键字之去重distinct 关键字之or ...

  8. vue引入高德地图

    一,下载 npm install vue-amap --save 二,main.js文件内引入 import VueAMap from 'vue-amap' Vue.use(VueAMap); // ...

  9. vue-cli3打包时vue-cli-service build怎么分不同环境(npm run build:stage和npm run build:prod)

  10. Redis基本操作(2)

    一.list类型 列表的元素类型为string 按照插⼊顺序排序 增加.修改 例1:在左侧插⼊数据 lpush key value1 value2 ... 例2:在右侧插⼊数据 rpush key v ...