Leetcode18 4Sum
暴力解法O(n^4),太恐怖了。
3Sum思路:转化,降维,排序+两层外循环内部两指针(一左一右),O(n^3)。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<>();
if(nums==null||nums.length<4) return ans;
Arrays.sort(nums);
for(int i=0;i<nums.length-3;i++) {
if(i==0||(i>0&&nums[i]!=nums[i-1])) {
for(int j=i+1;j<nums.length-2;j++) {
if(j>0&&nums[j]!=nums[j-1]) {
int low=j+1,high=nums.length-1,temp_target=target-nums[i]-nums[j];
while(low<high) {
if(nums[low]+nums[high]==temp_target) {
ans.add(Arrays.asList(nums[i],nums[j],nums[low],nums[high]));
while(low<high&&nums[low]==nums[low+1]) low++;
while(low<high&&nums[high]==nums[high-1]) high--;
low++;high--;
}
else if(nums[low]+nums[high]>temp_target) {
high--;
}
else {
low++;
}
}
}
}
}
}
return ans;
}
}
出错:
Input:[0,0,0,0] 0
Output:[]
Expected:[[0,0,0,0]]
查错的过程对
if(i==0||(i>0&&nums[i]!=nums[i-1]))
理解的更深了。i==0并不只是保证nums[i-1]存在,而是对于第一个一定要进入循环。
更正后可用:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new ArrayList<>();
if(nums==null||nums.length<4) return ans;
Arrays.sort(nums);
for(int i=0;i<nums.length-3;i++) {
if(i==0||(i>0&&nums[i]!=nums[i-1])) {
for(int j=i+1;j<nums.length-2;j++) {
if(j==i+1||(j>i+1&&nums[j]!=nums[j-1])) {
int low=j+1,high=nums.length-1,temp_target=target-nums[i]-nums[j];
while(low<high) {
if(nums[low]+nums[high]==temp_target) {
ans.add(Arrays.asList(nums[i],nums[j],nums[low],nums[high]));
while(low<high&&nums[low]==nums[low+1]) low++;
while(low<high&&nums[high]==nums[high-1]) high--;
low++;high--;
}
else if(nums[low]+nums[high]>temp_target) {
high--;
}
else {
low++;
}
}
}
}
}
}
return ans;
}
}
两次70ms附近 20%多,最好34ms,79%。还是有更好的方法的。
更好的方法:15ms方法 O(n^3)加剪枝,下次做可以尝试加上。11ms方法dfs,略复杂,下次想看可以看不想看算了。

浙公网安备 33010602011771号