Leecode-15 三數之和

題目要求:

給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/3sum

示例:

給定數組 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合爲:
[
[-1, 0, 1],
[-1, -1, 2]
]

思路:

很明顯,第一個辦法就是暴力法:

  1. 先排序
  2. 找到數組中的第一個元素,判斷是否 > 0,true 直接返回結果。
  3. 找到第二個元素,判斷這兩個元素相加是否 > 0 true 直接返回結果
  4. 從第三個位置,開始往後依次找能讓三數相加==0的值,找到就加入list,(然後對第二個位置的數往後移,繼續第3、4步)沒找到就第二次循環

這樣的時間複雜度肯定很高,已經接近了O(N³),肯定不是我們想要的結果,而且提交該答案也會報超時。

一個數去找另一個數,加起來再去找最後一個數太慢了
我們可以用雙指針,前後各一個指針,中間的數通過for循環依次更新
依然是先排序,每次更新完middle之後, 就計算left + right + middle的和,如果和大於0了 ,right-- ;如果小於0, left++ 直到找到 == 0的組合,或者找不到 == 0的組合

整理一下,這個時候我們再去考慮一下去重的問題和特殊判斷
特殊判斷可以讓特殊情況下不進行那麼多的步驟
比如

  1. 排序完後,nums[0] > 0 直接返回結果
  2. 或者數組的長度小於3 也直接返回
  3. 或者數組爲null
  4. 去重的話,主要就是每次left 和 right移動的時候,判斷是否移動之後的項和移動之前的項相同,這樣就可以達到去重的目的了

代碼

//排序+雙指針
    public static List<List<Integer>> threeSumDemo(int[] nums) {
        List<List<Integer>> result = new LinkedList<>();
        int length = nums.length;
        if(nums.length < 3)
            return result;
        Arrays.sort(nums);
        if(nums[0] > 0){
            return result;
        }
        for(int i = 0; i < length - 2; i++){
            //去重,排序過後  相同的值都在一起
            if(i > 0 && nums[i] == nums[ i - 1]){
                continue;
            }
            int middle = i + 1;
            int end = length - 1;
            int sum = -nums[i];
            while (middle < end){
                if (nums[middle] + nums[end] + nums[i] < 0 || (middle > i + 1 && nums[middle] == nums[middle - 1])) {
                    middle++;
                } else {
                    if (nums[middle] + nums[end] + nums[i] > 0 || (end < nums.length - 1 && nums[end] == nums[end + 1])) {
                        end--;
                    } else {
                        result.add(Arrays.asList(nums[i], nums[middle], nums[end]));
                        middle++;
                        end--;
                    }
                }
            }
        }
        return result;
    }
//暴力法,超時
    public static List<List<Integer>> threeSum(int[] nums) {
        if(nums.length == 0 || nums == null)
            return new LinkedList<>();
        int len = nums.length;
        Arrays.sort(nums);
        Set<List<Integer>> ans = new HashSet<>();
        List<List<Integer>> ans2 = new LinkedList<>();
        for(int i = 0 ;i < len - 2; i++) {
            if(nums[i] > 0)
                break;
            else {
                int j = i + 1;
                int tmp = nums[i] + nums[j];
                while (j < len - 1 && tmp <= 0)
                {
                    for(int k = j + 1; k < len; k++) {
                        List<Integer> list = new LinkedList<>();
                        if (tmp + nums[k] > 0)
                            break;
                        else if (tmp + nums[k] == 0) {
                            list.add(nums[i]);
                            list.add(nums[j]);
                            list.add(nums[k]);
                            ans.add(list);
                        }
                    }
                    j++;
                    tmp = nums[i] + nums[j];
                }
            }
        }
        for(List<Integer> list : ans) {
            ans2.add(list);
        }
        return ans2;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章