赞
踩
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结束。
代码:
- class Solution {
- public List<List<Integer>> threeSum(int[] nums) {
- List <List<Integer>> lists=new ArrayList<>();
- Arrays.sort(nums);
- if(nums.length<3) return lists;
- for(int i=0;i<nums.length-2;i++){ //遍历三数的最小数
- int L=i+1;
- int R=nums.length-1;
- if(i>0 && nums[i]==nums[i-1]) continue;
- while(L<R){ //双指针运动确定剩下两个数
- if(nums[i]>0) return lists;
- int tmp=nums[i]+nums[L]+nums[R];
- if(tmp==0){
- lists.add(Arrays.asList(nums[i],nums[L],nums[R]));
- while(L<R && nums[L+1]==nums[L]) L++;
- while(L<R && nums[R-1]==nums[R]) R--;
- L++;
- R--;
- }
- else if(tmp<0)
- L++;
- else if(tmp>0)
- R--;
- }
- }
- return lists;
- }
- }
-

2、三数和最接近目标数:
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
#题解:
用上述指针思路,不过有点暴力不算优:
- class Solution {
- public int threeSumClosest(int[] nums, int target) {
- if(nums.length<3) return 0;
- int totarget=999999;
- int Sums=0;
- Arrays.sort(nums);
- //[-1,0,1,1,55]
- for(int i=0;i<nums.length-2;i++){
- int L=i+1;
- int R=nums.length-1;
- while(L<R){
- int sum=nums[i]+nums[L]+nums[R];
- if(Math.abs(sum-target)<totarget){
- totarget=Math.abs(sum-target);
- Sums=sum;
- }
- if(sum==target) return Sums;
- else if(sum<target) L++;
- else if(sum>target) R--;
- }
- }
- return Sums;
- }
- }

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是一样的,只是要多一层嵌套循环。三数时只需要把最小数遍历,然后指针移动剩余两数即可。而四数则需要双层嵌套遍历最小的两个数,再把剩下的两个数进行指针移动。注意:如何避免输出重复解是此题最容易出错的地方,我自己提交报错了好几次才完全解决。
- class Solution {
- public List<List<Integer>> fourSum(int[] nums, int target) {
- List <List<Integer>> result=new ArrayList<>();
- if(nums.length<4 || nums==null) return result;
- Arrays.sort(nums);
- for(int i=0;i<nums.length-3;i++){ //遍历四数中的最小数
- int R=nums.length-1;
- if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
- if(nums[i]+nums[R]+nums[R-1]+nums[R-2]<target) continue;
- if(i>0 && nums[i]==nums[i-1]) continue; //去重复解
- for(int j=i+1;j<nums.length-2;j++){ //遍历第二小的数
- int L=j+1;
- R=nums.length-1;
- if(nums[i]+nums[j]+nums[R-1]+nums[R]<target) continue;
- if(j>i+1 && nums[j]==nums[j-1]) continue; //去重复解
- while(L<R){ //对剩下的两个数进行左右指针运动
- if(nums[i]+nums[j]+nums[L]+nums[R]==target){
- result.add(Arrays.asList(nums[i],nums[j],nums[L],nums[R]));
- while(L<R && nums[L+1]==nums[L]) L++; //去重复解
- while(L<R && nums[R-1]==nums[R]) R--;
- L++;
- R--;
- }
- else if(nums[i]+nums[j]+nums[L]+nums[R]<target) L++;
- else if(nums[i]+nums[j]+nums[L]+nums[R]>target) R--;
- }
- }
- }
- return result;
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。