当前位置:   article > 正文

leetcode刷题笔记5——三数和为0、三数和最接近目标数、四数和为目标数

leetcode刷题笔记5——三数和为0、三数和最接近目标数、四数和为目标数

1、三数和为0:

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

#题解:

看评论发现了一个用到指针的算法快速且容易理解,所以在经过理解和自己复写一遍后在此留下笔记。其方法主要是:1、数组从小到大排序;2、循环遍历数组确定三元组中的最小的第一个数nums[i];3、令L=i+1、R=nums.length-1;4、在固定nums[i]的前提下让L和R夹逼,途中把满足条件的三元组添加到lists中;5、遍历途中nums[i+1]==nums[i]则直接跳过,循环直到nums[i]>0结束。

代码: 

  1. class Solution {
  2.     public List<List<Integer>> threeSum(int[] nums) {
  3.         List <List<Integer>> lists=new ArrayList<>();
  4.         Arrays.sort(nums);
  5.         if(nums.length<3return lists;
  6.         for(int i=0;i<nums.length-2;i++){ //遍历三数的最小数
  7.             int L=i+1;
  8.             int R=nums.length-1;
  9.             if(i>0 && nums[i]==nums[i-1]) continue;
  10.             while(L<R){ //双指针运动确定剩下两个数
  11.                 if(nums[i]>0return lists;
  12.                 int tmp=nums[i]+nums[L]+nums[R];
  13.                 if(tmp==0){
  14. lists.add(Arrays.asList(nums[i],nums[L],nums[R]));
  15.                     while(L<R && nums[L+1]==nums[L]) L++;
  16.                     while(L<R && nums[R-1]==nums[R]) R--;
  17.                     L++;
  18.                     R--;
  19.                 }
  20.                 else if(tmp<0)
  21.                     L++;
  22.                 else if(tmp>0)
  23.                     R--;
  24.             }
  25.         }
  26.         return lists;
  27.     }
  28. }

2、三数和最接近目标数:

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

#题解:

用上述指针思路,不过有点暴力不算优:

  1. class Solution {
  2. public int threeSumClosest(int[] nums, int target) {
  3. if(nums.length<3) return 0;
  4. int totarget=999999;
  5. int Sums=0;
  6. Arrays.sort(nums);
  7. //[-1,0,1,1,55]
  8. for(int i=0;i<nums.length-2;i++){
  9. int L=i+1;
  10. int R=nums.length-1;
  11. while(L<R){
  12. int sum=nums[i]+nums[L]+nums[R];
  13. if(Math.abs(sum-target)<totarget){
  14. totarget=Math.abs(sum-target);
  15. Sums=sum;
  16. }
  17. if(sum==target) return Sums;
  18. else if(sum<target) L++;
  19. else if(sum>target) R--;
  20. }
  21. }
  22. return Sums;
  23. }
  24. }

3、四数和为目标数:

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

#题解:

此题跟三数和为0是一样的,只是要多一层嵌套循环。三数时只需要把最小数遍历,然后指针移动剩余两数即可。而四数则需要双层嵌套遍历最小的两个数,再把剩下的两个数进行指针移动。注意:如何避免输出重复解是此题最容易出错的地方,我自己提交报错了好几次才完全解决。

  1. class Solution {
  2. public List<List<Integer>> fourSum(int[] nums, int target) {
  3. List <List<Integer>> result=new ArrayList<>();
  4. if(nums.length<4 || nums==null) return result;
  5. Arrays.sort(nums);
  6. for(int i=0;i<nums.length-3;i++){ //遍历四数中的最小数
  7. int R=nums.length-1;
  8. if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
  9. if(nums[i]+nums[R]+nums[R-1]+nums[R-2]<target) continue;
  10. if(i>0 && nums[i]==nums[i-1]) continue; //去重复解
  11. for(int j=i+1;j<nums.length-2;j++){ //遍历第二小的数
  12. int L=j+1;
  13. R=nums.length-1;
  14. if(nums[i]+nums[j]+nums[R-1]+nums[R]<target) continue;
  15. if(j>i+1 && nums[j]==nums[j-1]) continue; //去重复解
  16. while(L<R){ //对剩下的两个数进行左右指针运动
  17. if(nums[i]+nums[j]+nums[L]+nums[R]==target){
  18. result.add(Arrays.asList(nums[i],nums[j],nums[L],nums[R]));
  19. while(L<R && nums[L+1]==nums[L]) L++; //去重复解
  20. while(L<R && nums[R-1]==nums[R]) R--;
  21. L++;
  22. R--;
  23. }
  24. else if(nums[i]+nums[j]+nums[L]+nums[R]<target) L++;
  25. else if(nums[i]+nums[j]+nums[L]+nums[R]>target) R--;
  26. }
  27. }
  28. }
  29. return result;
  30. }
  31. }

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号