这类问题暴力方法就是一层循环套着一层循环,所以 3sum 的时间复杂度就是O(n3),4sum的时间复杂度就是O(n4);
那么对于里面的两层循环可以做一个优化,想要做优化前需要对已有的数组排序,然后再使用双指针,所以可以总结两点算法优化的小技巧:排序+双指针
3sum
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++){
if(i>0){
while(i<nums.length-2 && nums[i-1]==nums[i] )
i++;
}
int left=i+1,right=nums.length-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]==0){
List<Integer> temp=new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[left]);
temp.add(nums[right]);
res.add(temp);
left++;
right--;
while(left<right && nums[left-1]==nums[left] )
left++;
while(right>left && nums[right+1]==nums[right])
right--;
}else if(nums[i]+nums[left]+nums[right]>0)
right--;
else
left++;
}
}
return res;
}
}
4sum
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length-3;i++){
if(i>0){
while(i<nums.length-3 && nums[i-1]==nums[i])
i++;
}
for(int j=i+1;j<nums.length-2;j++){
if(j>i+1){
while(j<nums.length-2 && nums[j-1]==nums[j])
j++;
}
int left=j+1,right=nums.length-1;
while(left<right){
int sum=nums[i]+nums[j]+nums[left]+nums[right];
if(sum==target){
List<Integer> temp=new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[left]);
temp.add(nums[right]);
res.add(temp);
left++;
right--;
while(left<right && nums[left]==nums[left-1])
left++;
while(left<right && nums[right+1]==nums[right])
right--;
}else if(sum>target)
right--;
else
left++;
}
}
}
return res;
}
}
3sum closest
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
boolean flag=false;
int res=0;
for(int i=0;i<nums.length-2;i++){
if(i>0)
while(i<nums.length-2 && nums[i-1]==nums[i])
i++;
int left=i+1,right=nums.length-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(!flag){
flag=true;
res=sum;
}
else if(sum==target)
return target;
else{
if(Math.abs(sum-target)<Math.abs(res-target))
res=sum;
if(sum>target)
right--;
else
left++;
}
}
}
return res;
}
}