1. 程式人生 > >LeetCode(1)三數之和為0

LeetCode(1)三數之和為0

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

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

例如, 給定陣列 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合為: [ [-1, 0, 1], [-1, -1, 2] ]

一,暴力法,直接用三個指標遍歷陣列

public static List<List<Integer>> threeSum(int[] nums)
        {
            Arrays.sort(nums);           //陣列排序
            List<List<Integer>> outList = new ArrayList<List<Integer>>();     //定義一個ArrayList線性表
            for (int i = 0; i < nums.length; i++)
            {
                if ((i > 0 && nums[i] == nums[i - 1]))      //去重,做判斷。如果符合條件就返回迴圈,對應的i直接跳過
                    continue;                     
                for (int j = i + 1; j < nums.length; j++)
                {
                    if ((j > i + 1 && nums[j] == nums[j - 1]))       //去重
                        continue;                        
                    for (int k = j + 1; k < nums.length; k++)
                    {
                        if ((k > j + 1 && nums[k] == nums[k - 1]))     //去重
                            continue;
                        if ((nums[i] + nums[j] + nums[k] == 0))        //判斷和為零
                        {
                            outList.add(Arrays.asList(nums[i],nums[j],nums[k]));   //新增到ArrayList中
                            break;
                        }
                    }
                }
            }
            return outList;        //返回找到的符合條件的陣列
        } 

最終測試程式碼在這裡插入圖片描述

這時我們發現,超時了。仔細分析我們知道迴圈太多了,而且都是三個for巢狀,這樣直接導致了時間複雜度飆升
那麼我們想辦法降低下時間複雜度。

二,頭尾指標法
方法一是三個指標依次陣列後面移,那麼我們試下頭尾加指標,縮小範圍來減小時間複雜度

public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        for (int i = 0; i + 2 < nums.length; i++)
        {
            if (i > 0 && nums[i] == nums[i - 1]) {     //去重
                continue;
            }
            int j = i + 1, k = nums.length - 1;
            int target = -nums[i];
            while (j < k)
            {
                if (nums[j] + nums[k] == target)
                {
                    res.add(Arrays.asList(nums[i], nums[j], nums[k]));   //新增到新的陣列
                    j++;  k--;
                    while (j < k && nums[j] == nums[j - 1]) j++;  //  各迴圈起始點不需要判斷重複
                    while (j < k && nums[k] == nums[k + 1]) k--;  //  各迴圈起始點不需要判斷重複
                } else if (nums[j] + nums[k] > target)
                   {
                       k--;         //k左移
                    } else {
                       j++;         //j右移
                   }
            }
        }
        return res;
    }

有問題歡迎留言哦

參考:

https://leetcode.com/problems/3sum/discuss/?orderBy=recent_activity