โจทย์ปัญหา
ได้รับอาร์เรย์ 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:
- Sort อาร์เรย์ก่อน
- ฟังก์ชัน
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