Skip to content
Rain Hu's Workspace
Go back

[LeetCode] 18. 4Sum

Rain Hu

18. 4Sum


一、題目

Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:

Example 1:

Example 2:

Constraints:


二、分析

三、解題

1. KSum

vector<vector<int>> fourSum(vector<int>& nums, int target) {
    sort(begin(nums), end(nums));       // 注意需先做排序
    return kSum(nums, target, 0, 4);
}

vector<vector<int>> kSum(vector<int>& nums, long long target, int start, int k) {
    vector<vector<int>> res;
    if (nums.size() < k) return res;    // 若數組的大小小於 k 則無解

    // #優化1: 數組已無剩餘數字可用
    if (start == nums.size()) return res;
    // #優化2: 數組的最小值的 k 倍需大於 target,數組的最大值的 k 倍需小於 target,但用乘法會超出 int 範圍,故用除法
    if (target/k < nums[start]|| target/4 > nums.back()) return res;

    if (k == 2) return twoSum(nums, target, start);

    for (int i = start; i < nums.size()-k+1; i++) {
        vector<vector<int>> subsets = kSum(nums, target-nums[i], i+1, k-1);
        for (vector<int>& subset : subsets) {
            res.push_back({nums[i]});   // 加入 nums[i]
            res.back().insert(end(res.back()), begin(subset), end(subset));   // 加入符合以 -nums[i] 為 target 的 (k-1)Sum
        }
        while (i+1 < nums.size()-k+1 && nums[i] == nums[i+1]) i++;      // 避免重覆數組解
    }


    return res;
}

vector<vector<int>> twoSum(vector<int>& nums, int target, int start) {     // nums 為 sorted array
    vector<vector<int>> res;
    int left = start;       // 注意 left pointer 是從 nums[i] 的下一位開始,即 i+1,我們將之訂為 start
    int right = nums.size()-1;
    while (left < right) {
        int sum = nums[left] + nums[right];
        if (sum < target) {
            while (left+1 < right && nums[left] == nums[left+1]) left++;        // 優化,跳過重覆的值
            left++;
        } else if (sum > target) {
            while (right-1 > left && nums[right-1] == nums[right]) right--;     // 優化,跳過重覆的值
            right--;
        } else {
            res.push_back({nums[left], nums[right]});
            while (left+1 < right && nums[left] == nums[left+1]) left++;        // 避免重覆數組
            while (right-1 > left && nums[right-1] == nums[right]) right--;     // 避免重覆數組
            left++;
            right--;
        }
    }
    return res;
}

回目錄 Catalog


Share this post on:

Previous
[LeetCode] 2156. Find Substring With Given Hash Value
Next
[LeetCode] 17. Letter Combinations of a Phone Number