🛑 1. The Problem First: การแก้ปัญหาแบบ "ตามมีตามเกิด"
ลองดูโจทย์คลาสสิก: "หาผลรวมของตัวเลขในลิสต์ที่ซ้อนกันไม่รู้กี่ชั้น" (Nested Array)
// ❌ Naive Approach: ใช้ Loop ซ้อน Loop (ถ้าซ้อน 10 ชั้น ก็ต้องเขียน 10 loops?)
const data = [1, [2, [3, 4], 5]];
let sum = 0;
data.forEach((item) => {
if (Array.isArray(item)) {
item.forEach((subItem) => {
if (Array.isArray(subItem)) {
/* ...พอก่อน ยิ่งเขียนยิ่งเละ */
}
});
}
});
ปัญหา: ยิ่งข้อมูลซับซ้อน โค้ดคุณจะยิ่งบวมและอ่านยากจนแก้ไม่ได้ นี่คือเหตุผลที่เราต้องมี Algorithms มาจัดการ Logic ให้คงที่และสวยงามครับ
💡 2. Real-Life Analogy: การจัดเรียงหนังสือในห้องสมุด
ลองนึกภาพว่าคุณกำลัง "จัดระเบียบห้องสมุด".
- Sorting: คือการเรียงหนังสือตามชื่อ ก-ฮ ถ้าคุณไม่เรียงเลย (Unsorted) เวลาคนมาหาหนังสือ เขาต้องเดินดูทีละเล่มตั้งแต่ประตูทางเข้า (Linear Search)
- Binary Search: คือการที่หนังสือเรียงแล้ว คุณเปิดดูตรงกลางหมวด "ม" แล้วรู้ทันทีว่า "ก" ต้องอยู่ซีกซ้ายแน่นอน คุณไม่ต้องเสียเวลาเดินดูซีกขวาทั้งซีก!
- Recursion: เหมือนคุณเจอ "กล่องซ้อนกล่อง". เมื่อคุณเปิดกล่องใหญ่แล้วเจอคำสั่งว่า "ภารกิจเดิม: เปิดกล่องที่อยู่ข้างใน" คุณก็แค่ทำซ้ำขั้นตอนเดิมไปเรื่อยๆ จนกว่าจะไม่เหลือกล่องให้เปิด (Base Case)
🚀 3. Execution Journey: กระบวนการคิดซ้ำ (Recursion)
เมื่อคุณเรียก deepSum([1, [2, 3]]) นี่คือสิ่งที่เกิดขึ้นในหน่วยความจำ:
🛠 Step-by-step:
- Call 1: รับ
[1, [2, 3]]มา วนลูปเจอเลข1(บวกเข้า sum) เจอ[2, 3](ส่งไป Call 2) - Call 2: รับ
[2, 3]มา วนลูปเจอเลข2และ3(บวกกันได้ 5) แล้วส่งกลับไปหาต้นทาง - Return: Call 1 รับค่า 5 มาบวกกับ 1 ที่มีอยู่ ได้ผลลัพธ์สุดท้ายคือ 6
// ✅ Best Practice: เขียน Recursion ให้มีจุดจบเสมอ
function deepSum(arr) {
let sum = 0;
for (const item of arr) {
if (Array.isArray(item)) {
sum += deepSum(item); // 🛠 ภารกิจเดิมในระดับที่ลึกลงไป
} else {
sum += item; // 🏁 Base Case: เมื่อเจอค่าตัวเลขจริงๆ
}
}
return sum;
}
🪤 4. The Junior Trap: เวทมนตร์ที่ย้อนกลับมาทำร้ายของ .sort()
จูเนียร์มักจะมั่นใจใน .sort() ของ JavaScript มากเกินไป:
// ❌ Junior Trap: สั่ง Sort ตัวเลขโดยไม่ใส่เป้าหมาย
const scores = [1, 2, 10, 20];
scores.sort();
// ผลลัพธ์: [1, 10, 2, 20] 😱
ทำไมถึงพัง? เพราะโดย default ของ JS มันจะมองทุกอย่างเป็น String แล้วเทียบอักษรตัวหน้าก่อน "10" จึงมาก่อน "2" เหมือนคำว่า "Apple" มาก่อน "Banana"
✅ การแก้ไข: ต้องส่ง Function เปรียบเทียบ (a, b) => a - b เข้าไปเสมอ!
⚖️ 5. The Why Matrix: ท่าไหนเหมาะกับงานไหน?
| เทคนิค | ความเร็ว | ความยากในการเขียน | เหมาะกับ |
|---|---|---|---|
| Linear Search | 🐢 ช้า (O(N)) | ง่ายมาก | ข้อมูลน้อย, เรียงไม่เป็นระเบียบ |
| Binary Search | 🚀 เร็ว (O(log N)) | ปานกลาง | ข้อมูลเยอะและ เรียงแล้ว เท่านั้น |
| Recursion | 🙂 คงที่ | สวยและสั้น | ข้อมูลแบบ Tree, Folder, Comment |
| Iteration (Loop) | 🙂 คงที่ | ซับซ้อนถ้าข้อมูลลึก | เมื่อต้องการ Performance สูงสุด |
🎓 6. Senior Mindset Summary
การเป็น Senior ไม่ใช่คนที่ท่องจำสูตรอัลกอริทึมได้ทุกตัว แต่คือคนที่ "รู้ว่าเมื่อไหร่ควรใช้เครื่องมืออะไร" และเข้าใจพฤติกรรมแปลกๆ ของภาษา (อย่าง .sort()) เพื่อไม่ให้เกิดบั๊กที่คาดไม่ถึงในอนาคตครับ!