博客 / 詳情

返回

算法 - 哈希表 - 三數之和

力扣 15題 : 三數之和

給你一個整數數組 nums ,判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i != j、i != k 且 j != k ,同時還滿足 nums[i] + nums[j] + nums[k] == 0 。請

你返回所有和為 0 且不重複的三元組。

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

 

 

示例 1:

輸入:nums = [-1,0,1,2,-1,-4]
輸出:[[-1,-1,2],[-1,0,1]]
解釋:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元組是 [-1,0,1] 和 [-1,-1,2] 。
注意,輸出的順序和三元組的順序並不重要。
示例 2:

輸入:nums = [0,1,1]
輸出:[]
解釋:唯一可能的三元組和不為 0 。
示例 3:

輸入:nums = [0,0,0]
輸出:[[0,0,0]]
解釋:唯一可能的三元組和為 0 。

來源:力扣(LeetCode)
鏈接:https://leetcode.cn/problems/3sum
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解法1 ,使用哈希表映射

參考:算法 - 哈希表 - 兩數之和 與 四數之和


class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> listList = new ArrayList<>();
        //Set是為了去除重複的list子集
        Set<List<Integer>> s = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            int a = nums[i];
            Set<List<Integer>> sub = find2Pare(nums, i, 0 - a);
            s.addAll(sub);
        }
        listList.addAll(s);
        return listList;
    }

    /**
        把問題化解為兩數之和
     */
    Set<List<Integer>> find2Pare(int[] nums, int start,  int target){
        Set<List<Integer>> lls = new HashSet<>();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = start+1; i < nums.length; i++) {
            List<Integer> list = new ArrayList<>();
            if (map.get(target-nums[i]) != null) {
                list.add(nums[start]);
                list.add(nums[i]);
                list.add(target-nums[i]);
                Collections.sort(list);
                lls.add(list);
            }
            map.put(nums[i],i);
        }
        return lls;
    }

}

解法2 雙指針法

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        // 先做排序
        Arrays.sort(nums);

        List<List<Integer>> lls = new ArrayList<>();
        for(int i  = 0 ; i < nums.length-2; i++) {
            // 如果當前數值大於0 ,因為是有序數組,後面的數值都是不可能和為0的,直接返回
            if(nums[i] > 0){
                return lls;
            }
            //對第一個數值去重
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            int a = nums[i];
            int left = i+1;
            int right = nums.length-1;
            while(left < right){

                if(a + nums[left] + nums[right] == 0){
                    List<Integer> list = new ArrayList<>();
                    list.add(a);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    lls.add(list);
                    
                    // 去重在找到第一個元素之後執行
                    // 對right指針元素去重
                    while(left < right && nums[right] == nums[right-1]){
                        right--;
                    }
                    // 對left指針元素去重
                    while(left < right && nums[left]== nums[left+1]){
                        left++;
                    }

                    // 找到答案後,雙指針收縮
                    left++;
                    right--;
                }
                else if(a + nums[left] + nums[right] > 0){
                    right--;
                }else {
                    left++;
                }
            }
        }

        return lls;
    }

}
user avatar monday_pro 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.