leetcode三數之和--雙指針

題目鏈接:三數之和
題目描述:給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

示例:

給定數組 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合爲:
[
[-1, 0, 1],
[-1, -1, 2]
]

題目分析:關鍵在於不重複,那麼爲了不重複,可以先對數組排序,同時在遍歷過程中控制循環下標和相鄰元素是否相等的判斷,達到去重的目的。繼續說,由於三數之和是固定的,那麼我們在知道其中兩個數之後,第三個數是確定的,所以我們可以固定一個數,然後枚舉另外兩個數。另外兩個數和是確定的,只要其中一個增大,另外一個必定減少,因此,可以採用雙指針進行雙向並行遍歷,減少時間複雜度。
對於本題「雙指針」,當我們需要枚舉數組中的兩個元素時,如果我們發現隨着第一個元素的遞增,第二個元素是遞減的,那麼就可以使用雙指針的方法,將枚舉的時間複雜度從 O(N2)減少至O(N)。爲什麼是 O(N) 呢?這是因爲在枚舉的過程每一步中,「左指針」會向右移動一個位置(也就是題目中的 b),而「右指針」會向左移動若干個位置,這個與數組的元素有關,但我們知道它一共會移動的位置數爲O(N),均攤下來,每次也向左移動一個位置,因此時間複雜度爲 O(N)。

代碼:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        int i = 0,l ,r,sum;
        while(i < nums.length-2&&nums[i]<=0){
             l = i+1;
             r = nums.length-1;
          while(l<r){
             sum = nums[l]+nums[i]+nums[r];
             if(sum==0){
                 res.add(Arrays.asList(nums[l++],nums[i],nums[r--]));
                 //去重
                 while(l<r&&nums[l]==nums[l-1]) l++;
                 while(l<r&&nums[r]==nums[r+1]) r--;
             }else if(sum<0){
                 l++;
             }else
                 r--;
          }
            i++;
            //去重
            while(i<nums.length-2&&nums[i]==nums[i-1]) i++;
        }
        return res;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章