这两到题目很类似,都是利用头尾两个指针步步逼近的解题思路
一开始想到的暴力算法的时间复杂度是O(n^3)。暴力枚举主要是对于每一个数组坐标i,都会进行头尾两指针的修正逼近。这样就造成了大量的重复计算在里面
所以为了降低时间复杂度,先对数组进行升序的排序(会对得到结果的修正起到更好的租用)。然后将一根指针定个在i+1的位置上,另外一个nums.length-1的位置上,不断的去修正
注:i为何不去遍历I前面的元素,我认为,I左边的元素在最外层的for循环到达i-1的位置时,已经对包含i项的所有可能都进行了计算。所以无需考虑左边的元素
具体代码如下:
15 题 3Sum
public class Solution {
public List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> AL=new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++){
if(i>0&&nums[i]==nums[i-1])
continue;
int j=i+1;int k=nums.length-1;
int target=-nums[i];
while(j<k){
if(nums[j]+nums[k]==target){
AL.add(Arrays.asList(nums[i],nums[j],nums[k]));
j++;
k--;
while(j<k&&nums[j]==nums[j-1])j++;
while(j<k&&nums[k]==nums[k+1])k--;
}
else if(nums[j] + nums[k] > target){
k--;}
else if(nums[j]+nums[k]<target){
j++;
}
}
}
return AL;
}
}
16题 3Sum Closest
public class Solution {
public int threeSumClosest(int[] nums, int target) {
int result=10000000;int n=nums.length;
Arrays.sort(nums);
for(int i=0;i<n-2;i++) //在右边的元素一定被在它前面的元素算过一次,所以不用考虑左边的情况
{
int j=i+1;
int k=n-1;
while(j<k){
int sum=nums[i]+nums[j]+nums[k];
if(sum>target){
k--;
}else{
j++;
}
if (Math.abs(sum - target) < Math.abs(result - target)) {
result = sum;
}
}
}
return result;
}
}