leetcode 15
三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
此题和之前做过的一样,动用指针的思路。
值得分析的问题有两个:
1.对于有序数组,三数之和>0,则其中数字应该增大还是减小?
三数之和<0,则其中数字应该增大还是减小?
显然当三数之和>0,数应该减小。
三数之和<0,数应该增大。
所以可以采用指针,固定开头r遍历一遍,在剩余的数组里定义左指针t为开头,右指针l为结尾。
当三数之和>0,数应该减小,所以l–;
当三数之和<0,数应该增加,所以t++;
当t>=l时,r++;
2.无重复的集合。
一开始我选择使用set来解决,但是后来发现只要规避掉重复的数据就可以了。
当指针移动时,如果数据重复则继续移动。
对于[0,0,0]问题
由于指针一开始就分开,则必然遍历过如此情况。
code:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//指针法
List<List<Integer>> list=new LinkedList<List<Integer>>();
if(nums.length<3) return list;
Arrays.sort(nums);
int r=0;
int t=1;
int l=nums.length-1;
while(t<=nums.length-1)
{
if(r>nums.length-3) break;
int p=nums[r]+nums[t]+nums[l];
if(p==0)
{
List<Integer> al=new ArrayList<Integer>();
al.add(nums[r]);
al.add(nums[t]);
al.add(nums[l]);
list.add(al);
while(l>t&&nums[l]==nums[--l]);
while(l>t&&nums[t]==nums[++t]);
}
else if(p>0)
{
while(l>t&&nums[l]==nums[--l]);
}
else if(p<0)
{
while(l>t&&nums[t]==nums[++t]);
}
if(t>=l)
{
while(r<=nums.length-3&&nums[r]==nums[++r]);
t=r+1;
l=nums.length-1;
}
}
return list;
}
}
执行用时 :34 ms, 在所有 Java 提交中击败了58.39%的用户
内存消耗 :44.5 MB, 在所有 Java 提交中击败了98.17%的用户
leetcode 16
最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
这道题和上面一道思路相同,不多赘述。
code:
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums.length<3) return 0;
Arrays.sort(nums);
int r=0;
int t=1;
int l=nums.length-1;
int tar=100000;
while(true)
{
if(r>nums.length-3) break;
int p=nums[r]+nums[t]+nums[l];
if(Math.abs(target-p)<Math.abs(tar)) tar=target-p;
if(p==target) return target;
else if(p<target)
{
while(l-1>t&&nums[t]==nums[++t]);
}
else if(p>target)
{
while(l-1>t&&nums[l]==nums[--l]);
}
if(t==l-1)
{
p=nums[r]+nums[t]+nums[l];
if(Math.abs(target-p)<Math.abs(tar)) tar=target-p;
while(r<=nums.length-3&&nums[r]==nums[++r]);
t=r+1;
l=nums.length-1;;
}
}
return target-tar;
}
}
执行用时 :7 ms, 在所有 Java 提交中击败了55.62%的用户
内存消耗 :39.2 MB, 在所有 Java 提交中击败了5.25%
的用户