Big-O Notation
O(n²) — Quadratic Time
เรียนรู้ O(n²) Quadratic Time — operations ที่จำนวนขั้นตอนโตแบบกำลังสองของขนาดข้อมูล เกิดจาก nested loops และ sorting algorithm พื้นฐาน พร้อม 6 Labs ฝึกเขียน countPairs, findDuplicates, multiplicationTable, bubblePass, findClosestPair, และ selectionSort
O(n²) คืออะไร
O(n²) หรือ **Quadratic Time** หมายความว่า จำนวนขั้นตอนเติบโตแบบ **กำลังสอง**ของขนาดข้อมูล n — ถ้าข้อมูลโต 10 เท่า งานจะโตประมาณ 100 เท่า
ลองนึกภาพ: มีคน n คนในงานเลี้ยง และทุกคนต้องจับมือกับทุกคน — คนแรกจับมือ n-1 คน, คนที่สองจับมือ n-2 คน, ... รวมเป็น (n×(n-1))/2 ≈ n²/2 ครั้ง — นี่คือ O(n²) ยิ่งคนมาก ยิ่งทวีคูณเร็วมาก
ทำไม O(n²) ถึงเติบโตเร็ว
เพราะแต่ละรอบของ loop นอก (n รอบ) มี loop ในที่วิ่งตามสัดส่วน n อีกที — งานรวมจึงเป็น n × n = n²
| n (ขนาดข้อมูล) | O(n) ขั้นตอน | O(n²) ขั้นตอน | O(n log n) ขั้นตอน |
|---|---|---|---|
| 10 | 10 | 100 | ~33 |
| 100 | 100 | 10,000 | ~664 |
| 1,000 | 1,000 | 1,000,000 | ~9,966 |
| 10,000 | 10,000 | 100,000,000 | ~132,877 |
สังเกต: เมื่อ n เพิ่ม 10 เท่า (จาก 100 เป็น 1,000) O(n²) เพิ่ม 100 เท่า (10,000 → 1,000,000) — ต่างจาก O(n) ที่เพิ่มแค่ 10 เท่า
ตัวอย่าง O(n²): nested loop เทียบคู่
รูปแบบที่พบบ่อยที่สุดของ O(n²) คือ **nested loop** — loop นอกวิ่ง n รอบ และทุกรอบของ loop นอกมี loop ในวิ่งตามสัดส่วน n
กฎง่ายๆ: **loop นอก n รอบ × loop ใน n รอบ = n² รอบ → O(n²)**
ตัวอย่าง O(n²): ตรวจหาค่าซ้ำด้วย nested loop
การตรวจว่ามีค่าซ้ำใน array หรือไม่ด้วย nested loop — loop นอกไล่ทุกตัว, loop ในเทียบกับตัวที่อยู่ถัดไป — เป็น O(n²)
เทียบกับวิธีที่ใช้ Set: ใช้ Set = O(n) เร็วกว่า — แต่วิธี nested loop เป็น O(n²) ที่เข้าใจง่ายกว่าเมื่อเริ่มต้น
ตัวอย่าง O(n²): Bubble Sort / Selection Sort / Insertion Sort
Algorithm สำหรับเรียงลำดับขั้นพื้นฐาน เช่น **Bubble Sort**, **Selection Sort**, และ **Insertion Sort** ล้วนทำงานใน O(n²) — เพราะใช้ nested loops เปรียบเทียบและสลับข้อมูล
เราจะเจาะลึก Bubble Sort, Selection Sort, Insertion Sort เพิ่มเติมใน phase Basic Sorting — ตอนนี้ให้เข้าใจว่า nested loops เป็นหัวใจของ O(n²)
สิ่งที่ **ไม่ใช่** O(n²)
เข้าใจผิดบ่อยที่สุดคือ คิดว่า loop สองอันแยกกันเป็น O(n²) ความจริงคือ **ต้องซ้อนกัน** (nested) ถึงจะเป็น O(n²) — ถ้าอยู่แยกกันคนละบรรทัด ไม่ได้ซ้อนกัน จะเป็น O(n) + O(n) = O(2n) = O(n)
กฎง่ายๆ: **O(n²) = loop นอก × loop ใน — สอง loop อยู่ในกัน ไม่ใช่แยกกัน**
กฎสำคัญ: O(n²) Patterns
O(n²) — Quadratic Time
Operations ที่จำนวนขั้นตอนโตแบบกำลังสองของ n
Nested loop สองชั้น (เต็ม n × n)
loop นอกวิ่ง n รอบ, loop ในวิ่ง n รอบ — งานรวม = n²
การเทียบคู่ (pair comparison)
เทียบทุกคู่ = n(n-1)/2 ≈ n²/2 — ยังเป็น O(n²) (ตัดค่าคงที่)
Bubble Sort / Selection Sort / Insertion Sort
Sorting algorithm พื้นฐาน — nested loop = O(n²)
ตารางคูณ / matrix n×n
สร้างตาราง n×n = O(n²) เพราะต้องเติมทุกช่อง n² ช่อง
Single loop วิ่ง n รอบ
loop เดียว = O(n) ไม่ใช่ O(n²)
สอง loop แยกกัน (sequential loops)
O(n) + O(n) = O(2n) = O(n) — ไม่ใช่ O(n²)
Lab 1: นับจำนวนคู่ทั้งหมด
Lab 2: ตรวจหาค่าซ้ำด้วย nested loop
Lab 3: สร้างตารางคูณ n×n
Lab 4: Bubble sort หนึ่งรอบ
Lab 5: หาคู่ที่ใกล้กันที่สุด
Lab 6: Selection sort
สรุป O(n²) Operations
| Operation | ตัวอย่าง | ความเร็ว |
|---|---|---|
| นับจำนวนคู่ทั้งหมด | countPairs(n) | O(n²) |
| ตรวจหาค่าซ้ำ (nested loop) | findDuplicates(arr) | O(n²) |
| สร้างตาราง n×n | multiplicationTable(n) | O(n²) |
| Bubble sort หนึ่งรอบ | bubblePass(arr) | O(n) |
| หาคู่ที่ใกล้กันที่สุด | findClosestPair(arr) | O(n²) |
| Selection sort | selectionSort(arr) | O(n²) |
| Loop เดียว | for (const x of arr) | O(n) ❌ |
| Array access by index | arr[3] | O(1) ❌ |
ทบทวนความเข้าใจ
O(n²) — Quadratic Time
ทดสอบความเข้าใจเกี่ยวกับ O(n²) operations