leetcode-18. 4Sum
阿新 • • 發佈:2018-11-21
15題的變式
題意:
給出一個數組和目標和target,在陣列中找到四個數,使他們相加之和為target
我的思路: 雙層迴圈(最優解法即為O(N^2^))
51%, O(N^2^)
類似15題,先排序,外層是兩層迴圈,內層是兩個指標找剩餘兩個數的和
步驟:
1. 陣列排序
2. 雙層遍歷陣列nums[i]和nums[j],如果i>0且nums[i]不等於nums[i - 1]時,繼續二層迴圈;當==j> i + 1==(表示不是改變i重新迴圈後的第一個數)且nums[j]不等於nums[j - 1]時,繼續下面的操作
3. 設定指標low = j + 1,high = length - 1
3. 當low和high位置的數相加>target- nums[i] - nums[j]時,high–;
4. 當low和high的數相加小於時,low++;
5. 相等時,將目前的組合加入result,並且檢測low之後的數,若相同low++跳過,high之前的數,若相同high–跳過
改進:效率提高至82%!!!
==由此可見,涉及到多層迴圈的,提前判斷避免不必要的進入內迴圈是非常必要的。==
提高效率可以加上幾個判斷使得非法值一開始就能檢測出,避免不必要的迴圈
- 當nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target或者nums[i]+nums[j]+nums[j+1]+nums[j+2]>target時,證明該趟外層迴圈最小的和都比target大,跳出;
- nums[i]+nums[nums.length-1]+nums[nums.length-2]+nums[nums.length-3]
改進後的程式碼:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res= new ArrayList<>();
int len = nums.length;
if (len < 4) {
return res;
}
Arrays.sort(nums);
for (int i = 0; i < len - 3; i++) {
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)continue;
if(nums[i]+nums[nums.length-1]+nums[nums.length-2]+nums[nums.length-3]<target)continue;
if (i > 0 && nums[i - 1] == nums[i]) {
continue;
}
for (int j = i + 1; j < len - 2; j++) {
if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)continue; //second candidate too large
if(nums[i]+nums[j]+nums[nums.length-1]+nums[nums.length-2]<target)continue; //second candidate too small
if (j > i + 1 && nums[j - 1] == nums[j]) {
continue;
}
int low = j + 1;
int high = len - 1;
int temp = target - nums[i] - nums[j];
while (low < high) {
int sum = nums[low] + nums[high];
if (sum < temp) {
low++;
}
else if (sum > temp) {
high--;
}
else {
res.add(Arrays.asList(nums[i], nums[j], nums[low], nums[high]));
while (low < high && nums[low + 1] == nums[low]) {
low++;
}
while (low < high && nums[high - 1] == nums[high]) {
high--;
}
low++;
high--;
}
}
}
}
return res;
}
}