Induksi matematis adalah teknik pembuktian fundamental untuk pernyataan yang berlaku pada seluruh bilangan bulat non-negatif. Dalam DSA, induksi adalah tulang punggung pembuktian kebenaran algoritma rekursif, analisis kompleksitas, dan struktur data berbasis hierarki (seperti tree). Pada Chapter ini kita akan mempelajari prinsip induksi matematis, dua variasi utamanya (lemah dan kuat), serta penerapannya pada pembuktian rumus deret dan sifat algoritma.
Prinsip Induksi Matematis #
Misalkan P(n) adalah pernyataan yang bergantung pada bilangan bulat n ≥ n₀. Untuk membuktikan P(n) benar untuk semua n ≥ n₀, kita lakukan dua langkah:
- Kasus Dasar (Base Case): buktikan
P(n₀)benar. - Langkah Induksi (Inductive Step): asumsikan
P(k)benar untuk suatuk ≥ n₀(hipotesis induksi). Gunakan hipotesis ini untuk membuktikanP(k+1)benar.
Bila kedua langkah terpenuhi, maka P(n) benar untuk semua n ≥ n₀.
Induksi Lemah vs Induksi Kuat #
Terdapat dua variasi induksi:
Induksi Lemah (Weak Induction) #
Hipotesis induksi hanya mengasumsikan P(k). Cocok untuk rekursi yang hanya memanggil T(k) dari T(k+1), misalnya faktorial.
Induksi Kuat (Strong Induction) #
Hipotesis induksi mengasumsikan P(n₀), P(n₀+1), ..., P(k) semuanya benar. Cocok untuk rekursi yang memanggil beberapa langkah sebelumnya, misalnya Fibonacci atau merge sort yang membagi masalah menjadi T(k/2) dan T(k - k/2).
Contoh 1: Penjumlahan 1 sampai n #
Buktikan bahwa 1 + 2 + ... + n = n(n+1)/2 untuk semua n ≥ 1.
Pembuktian #
Kasus Dasar (n = 1): ruas kiri = 1, ruas kanan = 1·2/2 = 1. Keduanya sama. ✓
Langkah Induksi: asumsikan 1 + 2 + ... + k = k(k+1)/2 (hipotesis induksi). Buktikan 1 + 2 + ... + (k+1) = (k+1)(k+2)/2.
1 + 2 + ... + (k+1) = [1 + 2 + ... + k] + (k+1)
= k(k+1)/2 + (k+1) (berdasarkan hipotesis)
= (k+1) [k/2 + 1]
= (k+1)(k+2)/2Pembuktian selesai. ∎
Kode: Verifikasi Numerik #
#include <iostream>
long long jumlah(int n) {
long long total = 0;
for (int i = 1; i <= n; ++i) total += i;
return total;
}
long long rumus(int n) {
return 1LL * n * (n + 1) / 2;
}
int main() {
std::cout << "n\tjumlah(n)\trumus(n)\tsama?\n";
for (int n : {1, 5, 10, 100, 1000, 10000}) {
long long j = jumlah(n);
long long r = rumus(n);
std::cout << n << '\t' << j << '\t' << r
<< (j == r ? "\tYA" : "\tTIDAK") << '\n';
}
return 0;
}Output yang Dihasilkan:
n jumlah(n) rumus(n) sama?
1 1 1 YA
5 15 15 YA
10 55 55 YA
100 5050 5050 YA
1000 500500 500500 YA
10000 50005000 50005000 YABedah Kode Baris-per-Baris #
- Fungsi
jumlah: menghitung penjumlahan secara iteratif, sebagai ground truth untuk verifikasi. - Fungsi
rumus: mengimplementasikan rumus Gaussn(n+1)/2yang ingin kita buktikan. Kita pakai1LLuntuk memaksa perhitunganlong longagar tidak overflow untuknbesar. - Loop
{1, 5, 10, 100, 1000, 10000}: menguji beberapa nilainuntuk memverifikasi kesesuaian. - Output: untuk seluruh
n, hasiljumlahsama denganrumus. Verifikasi numerik ini bukan pembuktian formal, tetapi memberi keyakinan tambahan. - Implikasi: walaupun pembuktian formal dengan induksi sudah cukup, verifikasi numerik membantu menangkap kesalahan ketik atau kesalahan logika yang mungkin terjadi.
Contoh 2: Jumlah Kuadrat #
Buktikan bahwa 1² + 2² + ... + n² = n(n+1)(2n+1)/6 untuk semua n ≥ 1.
Pembuktian #
Kasus Dasar (n = 1): ruas kiri = 1, ruas kanan = 1·2·3/6 = 1. Sama. ✓
Langkah Induksi: asumsikan 1² + 2² + ... + k² = k(k+1)(2k+1)/6. Buktikan 1² + ... + (k+1)² = (k+1)(k+2)(2k+3)/6.
1² + ... + (k+1)² = [1² + ... + k²] + (k+1)²
= k(k+1)(2k+1)/6 + (k+1)²
= (k+1) [k(2k+1)/6 + (k+1)]
= (k+1) [(2k² + k + 6k + 6)/6]
= (k+1) [(2k² + 7k + 6)/6]
= (k+1)(k+2)(2k+3)/6Faktorisasi 2k² + 7k + 6 = (k+2)(2k+3) dapat diverifikasi dengan ekspansi. ∎
Contoh 3: Banyaknya Node pada Binary Tree Penuh #
Sebuah binary tree penuh dengan kedalaman d memiliki 2^(d+1) - 1 node (dengan kedalaman root = 0). Mari kita buktikan dengan induksi pada d.
Pembuktian #
Definisi: binary tree penuh dengan kedalaman d adalah tree yang setiap node internal (non-leaf) memiliki tepat dua anak, dan semua leaf berada pada kedalaman d.
Kasus Dasar (d = 0): tree hanya berisi root. Jumlah node = 1 = 2^1 - 1. ✓
Langkah Induksi: asumsikan binary tree penuh dengan kedalaman k memiliki 2^(k+1) - 1 node. Binary tree penuh dengan kedalaman k+1 dapat dibayangkan sebagai root yang memiliki dua sub-tree penuh berkedalaman k sebagai anak kiri dan kanan. Total node:
1 (root) + 2 × [jumlah node sub-tree berkedalaman k]
= 1 + 2 × (2^(k+1) - 1)
= 1 + 2^(k+2) - 2
= 2^(k+2) - 1Ini sesuai dengan rumus 2^(d+1) - 1 untuk d = k+1. ∎
Contoh 4: Kebenaran Faktorial Rekursif #
Fungsi factorial(n) berikut menghitung n!. Mari kita buktikan kebenarannya dengan induksi.
Kode Program #
#include <iostream>
long long factorial(int n) {
if (n <= 1) return 1;
return static_cast<long long>(n) * factorial(n - 1);
}
int main() {
for (int n : {0, 1, 5, 10, 20}) {
std::cout << "factorial(" << n << ") = " << factorial(n) << '\n';
}
return 0;
}Output yang Dihasilkan:
factorial(0) = 1
factorial(1) = 1
factorial(5) = 120
factorial(10) = 3628800
factorial(20) = 2432902008176640000Pembuktian Kebenaran #
Spesifikasi: factorial(n) mengembalikan n! untuk semua n ≥ 0.
Kasus Dasar (n = 0 dan n = 1): factorial(0) dan factorial(1) mengembalikan 1, yang sama dengan 0! = 1! = 1. ✓
Langkah Induksi: asumsikan factorial(k) benar, yaitu mengembalikan k!. Buktikan factorial(k+1) mengembalikan (k+1)!.
factorial(k+1) = (k+1) * factorial(k) // baris return
= (k+1) * k! // hipotesis induksi
= (k+1)! // definisi faktorialPembuktian selesai. ∎
Bedah Kode Baris-per-Baris #
- Baris
if (n <= 1) return 1;: base case —0! = 1dan1! = 1secara definisi. - Baris
return static_cast<long long>(n) * factorial(n - 1);: langkah induksi —n! = n × (n-1)!. Cast kelong longmenghindari overflow pada intermediate. - Output
factorial(20) = 2432902008176640000: nilai maksimum yang muat dilong long(signed 64-bit) adalah20!.21!akan overflow. - Implikasi: pembuktian kebenaran dengan induksi memberi jaminan bahwa
factorial(n)mengembalikann!untuk setiapn ≥ 0(asalkan tidak overflow).
Induksi pada Struktur Rekursif #
Induksi tidak terbatas pada bilangan bulat. Kita bisa menginduksi pada:
- Struktur tree: induksi pada kedalaman atau jumlah node.
- String: induksi pada panjang string.
- Graph: induksi pada jumlah simpul atau sisi.
- List: induksi pada panjang list.
Ringkasan #
- Induksi matematis membuktikan pernyataan
P(n)untuk semuan ≥ n₀melalui kasus dasar dan langkah induksi. - Induksi lemah mengasumsikan
P(k); induksi kuat mengasumsikanP(n₀), ..., P(k)semuanya. - Contoh klasik: rumus deret
1 + 2 + ... + n = n(n+1)/2, rumus kuadratn(n+1)(2n+1)/6, dan jumlah node binary tree penuh2^(d+1) - 1. - Pembuktian kebenaran algoritma rekursif sering kali memanfaatkan induksi: base case algoritma menjadi kasus dasar, recursive case menjadi langkah induksi.
- Structural induction adalah variasi untuk struktur rekursif seperti tree dan list.
Pada Chapter berikutnya kita akan menerapkan teknik loop invariant dan induksi untuk membuktikan kebenaran algoritma klasik seperti linear search dan insertion sort.