1. 程式人生 > >leetcode-18. 4Sum

leetcode-18. 4Sum

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; } }