Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

โจทย์ 4Sum ใน C++ (หา 4 ตัวที่รวมกันได้ Target)

โจทย์ปัญหา

ได้รับอาร์เรย์ n จำนวนเต็ม และค่า Target ให้หา ทุกชุดของ 4 ตัวเลข (Quadruplets) ที่ไม่ซ้ำกัน ที่มีผลรวมเท่ากับ Target

ตัวอย่าง

นำเข้า: nums = [-1,0,1,2,0,-2], target = 0
ผลลัพธ์: [[-1,0,0,1], [-2,-1,1,2], [-2,0,0,2]]

แนวคิดการแก้ปัญหา (Generalized k-Sum)

ขยายจาก 2Sum และ 3Sum โดยใช้ Recursive k-Sum:

  1. Sort อาร์เรย์ก่อน
  2. ฟังก์ชัน kSum(arr, start, k, target):
    • ถ้า k == 2: ใช้ Two Pointers หาคู่ที่รวมกันได้ target (ข้ามค่าซ้ำ)
    • ถ้า 2: วนลูป i จาก start ถึง n-k+1
      • ข้ามค่าซ้ำ: if (i > start && arr[i] == arr[i-1]) continue
      • เรียก kSum(arr, i+1, k-1, target - arr[i]) แบบ Recursive
      • นำผลลัพธ์มาต่อกับ arr[i]

โค้ดตัวอย่าง (C++)

#include <bits/stdc++.h>
using namespace std;

void print_vector(vector<vector<int>> v) {
    cout << "[";
    for (int i = 0; i < v.size(); i++) {
        cout << "[";
        for (int j = 0; j < v[i].size(); j++)
            cout << v[i][j] << ", ";
        cout << "],";
    }
    cout << "]" << endl;
}

class Solution {
public:
    void addAll(vector<vector<int>>& res, vector<vector<int>>& temp) {
        for (int i = 0; i < temp.size(); i++) res.push_back(temp[i]);
    }

    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        return kSum(nums, 0, 4, target);
    }

    vector<vector<int>> kSum(vector<int>& arr, int start, int k, int target) {
        vector<vector<int>> res;
        if (k == 2) {
            int left = start, right = arr.size() - 1;
            vector<int> temp(2);
            while (left < right) {
                if (arr[left] + arr[right] == target) {
                    temp[0] = arr[left]; temp[1] = arr[right];
                    res.push_back(temp);
                    while (left < right && arr[left] == arr[left + 1]) left++;
                    while (left < right && arr[right] == arr[right - 1]) right--;
                    left++; right--;
                } else if (arr[left] + arr[right] > target) right--;
                else left++;
            }
        } else {
            for (int i = start; i < (int)arr.size() - k + 1; i++) {
                if (i > start && arr[i] == arr[i - 1]) continue;
                vector<vector<int>> temp = kSum(arr, i + 1, k - 1, target - arr[i]);
                for (int j = 0; j < temp.size(); j++)
                    temp[j].push_back(arr[i]);
                addAll(res, temp);
            }
        }
        return res;
    }
};

int main() {
    Solution ob;
    vector<int> v = {1,0,-1,0,-2,2};
    print_vector(ob.fourSum(v, 0));
    return 0;
}

ผลลัพธ์

[[1,2,-1,-2],[0,2,0,-2],[0,1,0,-1]]

คำอธิบายเพิ่มเติม

  • ความซับซ้อนด้านเวลา: O(n³) สำหรับ 4Sum (โดยทั่วไป k-Sum ใช้ O(nk-1))
  • ความซับซ้อนด้านพื้นที่: O(n) สำหรับ recursion stack
  • การ Sort และการข้ามค่าซ้ำเป็นกุญแจสำคัญในการหลีกเลี่ยง duplicate quadruplets