ปัญหา
กำหนดเมทริกซ์ mat ขนาด m × n ที่แต่ละแถวเรียงลำดับจากน้อยไปมาก (Non-decreasing) และจำนวนเต็ม k ให้เลือก عنصرละ 1 ตัวจากแต่ละแถว เพื่อสร้างอาร์เรย์ แล้วหา ผลรวมที่เล็กที่สุดอันดับ K จากทุกอาร์เรย์ที่เป็นไปได้
ตัวอย่าง: mat = [[1,3,11],[2,4,6]], k = 5
ผลรวมที่เป็นไปได้ (เรียงจากน้อยไปมาก):
- [1,2] → 3
- [1,4] → 5
- [3,2] → 5
- [3,4] → 7
- [1,6] → 7 ← อันดับ 5
คำตอบ: 7
แนวคิดการแก้: Priority Queue + State Expansion
เริ่มจากผลรวมน้อยที่สุด (เลือกตัวแรกของทุกแถว) แล้วขยาย State โดยเพิ่มดัชนีในแถวทีละแถว ใช้ Min-Heap (Priority Queue) ดึงผลรวมน้อยสุดทีละอัน จนครบ K รอบ
State Representation
- เก็บ
[sum, idx_0, idx_1, ..., idx_{m-1}]โดยidx_i= ดัชนีที่เลือกในแถว i - เริ่มต้น:
[sum_of_first_elements, 0, 0, ..., 0] - จาก State ปัจจุบัน สร้าง State ใหม่โดยเพิ่ม
idx_iทีละ 1 (ถ้ายังไม่เกินขอบเขต)
ป้องกัน State ซ้ำ
ใช้ set<vector<int>> เก็บ State ที่เคยดึงออกจาก PQ แล้ว เพื่อไม่ให้ประมวลผลซ้ำ
โค้ด C++
#include <bits/stdc++.h>
using namespace std;
struct Cmp {
bool operator()(vector<int>& a, vector<int>& b) {
return !(a[0] < b[0]); // Min-heap by sum
}
};
class Solution {
priority_queue<vector<int>, vector<vector<int>>, Cmp> pq;
vector<vector<int>> m;
int z; // จำนวนคอลัมน์
void update(vector<int>& v, int i, bool ok = false) {
if (i == v.size()) {
if (!ok) return;
int sum = 0;
for (int j = 0; j < v.size(); j++) sum += m[j][v[j]];
vector<int> temp(v.begin(), v.end());
temp.insert(temp.begin(), sum);
pq.push(temp);
return;
}
v[i]++;
if (!ok && v[i] < z) update(v, i + 1, true);
v[i]--;
update(v, i + 1, ok);
}
public:
int kthSmallest(vector<vector<int>>& mat, int k) {
this->m = mat;
int n = m.size();
z = m[0].size();
int ret = 0;
for (int i = 0; i < n; i++) ret += m[i][0];
vector<int> temp(n);
temp.insert(temp.begin(), ret);
pq.push(temp);
set<vector<int>> visited;
while (k--) {
vector<int> cur = pq.top(); pq.pop();
visited.insert(cur);
ret = cur[0];
cur.erase(cur.begin()); // ลบ sum ออก เหลือแค่ indices
update(cur, 0);
while (!pq.empty() && visited.count(pq.top())) {
pq.pop();
}
}
return ret;
}
};
int main() {
Solution ob;
vector<vector<int>> v = {{1,3,11},{2,4,6}};
cout << ob.kthSmallest(v, 5); // 7
return 0;
}
ความซับซ้อน
- Time: O(k × m × log(k)) ประมาณ (m = จำนวนแถว)
- Space: O(k × m) สำหรับ PQ และ Visited Set
Input / Output
Input: {{1,3,11},{2,4,6}}, k=5
Output: 7