1. 程式人生 > >#15 3Sum

#15 3Sum

正確解法:

在排序之後,用for loop確定最小的數,然後讓剩下兩個指標在最小數的基礎上,分列兩邊,向中間靠攏。

關於重複的考慮:對於最小的指標,只需要保證最小的指標不一樣即可。對於另外兩個指標,只有在成功塞進結果列的情況下才需要考慮,這時候,只要把重複去掉就好了。

時間複雜度O(n2)。

 

我的問題:

  1. O(n3)次的複雜度:既然我這麼用了,其實排序並沒有帶給我積極的意義。排序本身的作用是利用這一串數字的排列,來減小時間複雜度。

  2. 對於重複的數字,實際有兩個bound來決定要不要繼續找數字。

    1. 有新的數存在

    2. 在a的基礎假設上,以a為動力,來移動指標

→ 用我的方法,存在一個問題,就是當這一串數字的末尾全是重複數字的時候,我無法
預知在後面是否還有新的數字存在。所以,其實從兩邊向中間的方法就可以解決這個問
題,我只要check左邊的指標永遠小於右指標就可以了。


修正後的程式碼:(只作為參考,記錄下來)

class Solution {
   public List<List<Integer>> threeSum(int[] nums) {
       List<List<Integer>> result = new ArrayList<>();
       if(nums.length < 3){
           return result;
       }
       Arrays.sort(nums);
       if(nums[0] > 0 || nums[nums.length-1] < 0){
           return result;
       }

       for(int i = 0; i < nums.length - 2; i++){
           if(i == 0 || nums[i - 1] != nums[i]){
               int j = i + 1;
               int k = nums.length - 1;
               while(j < k){
                   if(nums[i] == - (nums[j] + nums[k])){
                       List<Integer> current = new ArrayList<>();
                       current.add(nums[i]);
                       current.add(nums[j]);
                       current.add(nums[k]);
                       result.add(current);
                   
                   
                       // check repeated values
                       while(j < k && nums[j] == nums[j + 1]){
                           j++;
                       }
                       while(j < k && nums[k] == nums[k - 1]){
                           k--;
                       }
                       j++;
                       k--;
                   }else if(nums[i] < - (nums[j] + nums[k])){   
                       // nums[j] + nums[k] can be larger
                       j++;
                   }else{
                       k--;
                   }
               }
           }
           
       }
       return result;
   }

}