Search
หลักการ
Search คือการลองสำรวจสถานะหรือคำตอบที่เป็นไปได้ทั้งหมดภายใต้เงื่อนไขของโจทย์ เทคนิคนี้เป็นพื้นฐานของ brute force, backtracking, graph traversal และ optimization หลายแบบ
ข้อดีคือคิดตรงไปตรงมาและใช้ตรวจคำตอบของวิธีที่ซับซ้อนได้ ข้อเสียคือ state space มักโตเร็วมาก จึงต้องวิเคราะห์จำนวนสถานะก่อนเขียนจริง
Motivation problem
สมมติมีตัวเลข n ตัว และต้องเลือกบางตัวให้ผลรวมเท่ากับ x วิธี brute force คือพิจารณาทุก subset
for (int mask = 0; mask < (1 << n); mask++) {
int sum = 0;
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) sum += a[i];
}
if (sum == x) {
cout << "found";
}
}
จำนวน subset คือ 2n ดังนั้นวิธีนี้เหมาะกับ n ≤ 20
Generating Permutations
เขียน recursive function เพื่อ generate ทุก permutation ที่เป็นไปได้
vector<int> p;
vector<bool> used(n);
void gen() {
if ((int)p.size() == n) {
// process permutation
return;
}
for (int i = 0; i < n; i++) {
if (used[i]) continue;
used[i] = true;
p.push_back(i);
gen();
p.pop_back();
used[i] = false;
}
}
จำนวน permutation คือ n! จึงใช้ได้เฉพาะ n เล็กมาก
Graph Traversal
VisuAlgo interactive visualizationvisualgo.net
BFS ใช้ queue และสำรวจตามระยะทางจากจุดเริ่มต้น เหมาะกับ shortest path ในกราฟไม่มีน้ำหนัก
DFS ใช้ recursion หรือ stack เหมาะกับ connectivity, cycle detection และ topological sort
preorder: ทำงานกับ node ก่อนเข้าลูก
inorder: ใช้กับ binary tree
postorder: ทำงานกับ node หลังออกจากลูก
Topological Sort
ตัวอย่าง BFS
queue<int> q;
vector<int> dist(n, -1);
dist[start] = 0;
q.push(start);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : adj[u]) {
if (dist[v] != -1) continue;
dist[v] = dist[u] + 1;
q.push(v);
}
}
Binary Search Tree
VisuAlgo interactive visualizationvisualgo.net
create
search(v)
insert(v)
remove(v)
Meet in the middle
เป็นเทคนิคที่ถ้า search จากต้นทางแล้ว space ใหญ่เกินไป ให้ search จากปลายทางแล้วมาเจอกันตรงกลาง
ตัวอย่างเช่น subset sum ที่ n = 40 ถ้าลองทุก subset จะเป็น 240 ซึ่งมากเกินไป แต่ถ้าแบ่ง array เป็นสองครึ่ง จะได้สองชุดขนาด 220 แล้วนำผลรวมของสองฝั่งมาจับคู่กัน
ขั้นตอนทั่วไป
แบ่งข้อมูลเป็นสองส่วน
generate คำตอบย่อยของแต่ละส่วน
sort หรือใช้ hash เพื่อหาคู่ที่รวมกันเป็นคำตอบ
การเลือกเทคนิค
เทคนิค |
จำนวนสถานะ |
ใช้เมื่อ |
|---|---|---|
Subset brute force |
O(2n) |
n เล็กและต้องลองเลือกหรือไม่เลือก |
Permutation brute force |
O(n!) |
ต้องลองลำดับทั้งหมด |
BFS |
O(V + E) |
กราฟไม่มีน้ำหนักหรือหาจำนวนก้าวน้อยสุด |
DFS |
O(V + E) |
สำรวจ component, cycle, ordering |
Meet in the middle |
$O\left( 2^{\left\{ \frac{n}{2} \right\}} \right)$ |
n กลาง ๆ เช่น 30-44 |
ข้อควรระวัง
ต้องกำหนด state ให้ชัดว่าอะไรคือข้อมูลที่จำเป็นต่อการตัดสินใจต่อไป
อย่าลืม mark visited ใน graph search ไม่เช่นนั้นอาจวนไม่จบ
ถ้าใช้ recursion ลึกมาก อาจ stack overflow ได้
วิเคราะห์จำนวนสถานะก่อนเสมอ เพราะ search ที่ถูกต้องแต่ช้าเกินไปจะไม่ผ่านเวลา