โจทย์ปัญหา
ได้รับอาร์เรย์ nums ขนาด n และค่า target ให้หา 3 จำนวนในอาร์เรย์ ที่ผลรวม ใกล้เคียงกับ target มากที่สุด คืนค่าผลรวมนั้น (รับประกันว่ามีคำตอบเพียง 1 ชุด)
ตัวอย่าง
นำเข้า: nums = [-1, 2, 1, -4], target = 1
ผลลัพธ์: 2
คำอธิบาย: Triplet [-1, 2, 1] ให้ผลรวม 2 ใกล้ target=1 มากที่สุด (ความต่าง = 1)
แนวคิดการแก้ปัญหา (Two Pointers + Sorting)
- Sort อาร์เรย์
- กำหนด
ans = 0,diff = INT_MAX - วนลูป
iจาก 0 ถึง n-1:- ตั้ง
left = i+1,right = n-1 - ขณะ
left < right:sum = nums[i] + nums[left] + nums[right]- ถ้า
|target - sum| < diff: อัปเดตans = sum,diff = |target - sum| - ถ้า
sum == target: คืนค่าsumทันที (เจอคำตอบที่ดีที่สุดแล้ว) - ถ้า
target:right--(ลดผลรวม) - ถ้า
sum < target:left++(เพิ่มผลรวม)
- ตั้ง
- คืนค่า
ans
โค้ดตัวอย่าง (C++)
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int ans = 0;
int diff = INT_MAX;
int n = nums.size();
for (int i = 0; i < n; i++) {
int left = i + 1;
int right = n - 1;
while (left < right) {
int sum = nums[left] + nums[right] + nums[i];
if (abs(target - sum) < diff) {
ans = sum;
diff = abs(target - sum);
}
if (sum == target) return sum;
else if (sum > target) right--;
else left++;
}
}
return ans;
}
};
int main() {
Solution ob;
vector<int> v = {-1, 2, 1, -4};
cout << ob.threeSumClosest(v, 1);
return 0;
}
ผลลัพธ์
2
คำอธิบายเพิ่มเติม
- ความซับซ้อนด้านเวลา: O(n²) (Sort O(n log n) + Two pointers O(n²))
- ความซับซ้อนด้านพื้นที่: O(1) หรือ O(log n) สำหรับ sorting stack
- เทคนิค Two Pointers ใช้ได้เพราะอาร์เรย์ถูก Sort แล้ว
- ข้ามค่าซ้ำได้ด้วยการ
while (left < right && nums[left] == nums[left+1]) left++เพื่อประสิทธิภาพ