1. 程式人生 > >LeetCode15. 三數之和

LeetCode15. 三數之和

題目

給定一個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。

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

例如, 給定陣列 nums = [-1, 0, 1, 2, -1, -4],

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

分析

最一開始覺得就是需要遍歷所有情況呀,然後寫了一個很簡單暴力的三重迴圈,先陣列排序,方便去除重複元素,之後迴圈遍歷,最後超時啦。後來看了報告之後,發現可以將三重迴圈改進為兩重迴圈。

為了方便去除那些會重複的列表,我先把陣列按升序排序,這就成為了有序數列。我們要求的是3數之和,先找出第一個數字,然後找出另外兩個相加 + 第一個數 = 0,就可以了。第一個數就遍歷陣列,然後從i+1開始到len找另外兩個數字,第一個數字遍歷到正數的時候呢,就不用繼續向後找啦,因為後面的數字越來越大,第一個數都是正數了,後面也不用看啦。

再找兩數之和的時候不可以兩重迴圈啊,因為已經有序了,所以一個指標從前向後,一個指標從後向前,這樣找出合適的組合。

還有要注意的是去重去重去重。

程式碼

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list =  new ArrayList<List<Integer>>();

        Arrays.sort(nums);

        for (int i = 0; i < nums.length-2; i++) {
            if (nums[i] > 0 )break;
            if (i > 0 && nums[i-1] == nums[i]) //去重
                continue;

            for(int j = i+1, k = nums.length-1; j < k && j < nums.length && k >= 0;){
                if (nums[j] + nums[k] == -1 * nums[i]){
                    ArrayList<Integer> l = new ArrayList<Integer>();
                    l.add(nums[i]);l.add(nums[j]);l.add(nums[k]);
                    list.add(l);
                    while (j<k && nums[j] == nums[j+1]) j++;//去重
                    while (j<k && nums[k] == nums[k-1]) k--;//去重
                    j++;k--;
                }else if( nums[j] + nums[k] < nums[i] * -1){
                    j ++;
                }else{
                    k --;
                }
            }

        }
        return list;
    }
}