演算法前導

更新於 發佈於 閱讀時間約 6 分鐘

舉例介紹

寫同樣的一段程式碼,別人的code卻比自己寫的code還要有效率,也就是跑得更快,為什麼呢?

其根本原因很可能出在演算法的問題上。

找出所有質數(Prime Numbers) 為例,不同的演算法效率差異巨大。

以暴力解法來看:

#include <stdio.h>
#include <math.h>

// 判斷 n 是否為質數
int isPrime(int n) {
if (n < 2) return 0;
for (int i = 2; i < n; i++) {
if (n % i == 0)
return 0;
}
return 1;
}

// 找出範圍內所有質數
void findPrimes(int limit) {
for (int i = 2; i <= limit; i++) {
if (isPrime(i))
printf("%d ", i);
}
printf("\n");
}

int main() {
int limit = 100;
findPrimes(limit);
return 0;
}
  • 我們運行一個由 2 到 n 之間的迴圈,並對迴圈的每個值,判斷它是不是質數。

其實,有更快的檢查方法,我們透過將程式碼改為for (int i = 2; i <= sqrt(n); i++)可以優化整個程式的速度,尤其是範圍很大時。

#include <stdio.h>
#include <math.h>

// 判斷 n 是否為質數
int isPrime(int n) {
if (n < 2) return 0;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0)
return 0;
}
return 1;
}

// 找出範圍內所有質數
void findPrimes(int limit) {
for (int i = 2; i <= limit; i++) {
if (isPrime(i))
printf("%d ", i);
}
printf("\n");
}

int main() {
int limit = 100;
findPrimes(limit);
return 0;
}

for (int i = 2; i <= sqrt(n); i++) 這種方法比 for (int i = 2; i < n; i++) 更快的根本原因在於:

  • 如果 n 有因數,那麼它的最小因數必定小於等於 sqrt(n)
  • 超過 sqrt(n) 之後,所有的因數都是前面已經找到的因數的對應乘積,所以不需要再檢查。

舉例(n = 36):

所有的因數對:

(1, 36)
(2, 18)
(3, 12)
(4, 9)
(6, 6) <-- √36 = 6,之後開始重複
(9, 4) <-- 重複
(12, 3) <-- 重複
(18, 2) <-- 重複
(36, 1) <-- 重複

觀察發現,當 i > 6 (sqrt(36) = 6) 之後,我們只是在重複檢查已經出現過的因數對,所以沒必要再繼續檢查!

只要檢查到 sqrt(n),就能找到所有因數,沒必要再繼續迴圈。

  • 另外補充一點,你也可以將程式碼寫為for (int i = 2; i * i <= n; i++),其概念相同。

差異測試

如果我們要測試兩個程式碼執行時間上的差異,這個程式碼可以幫助我們:

#include <stdio.h>
#include <math.h>
#include <time.h>

// 方法 1:暴力法
int isPrimeBruteForce(int n) {
if (n < 2) return 0;
for (int i = 2; i < n; i++) {
if (n % i == 0)
return 0;
}
return 1;
}

// 方法 2:sqrt(n) 優化
int isPrimeOptimized(int n) {
if (n < 2) return 0;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0)
return 0;
}
return 1;
}

int main() {
int limit = 1000000;
clock_t start, end;
double time_used;

// 測試暴力法
start = clock();
for (int i = 2; i <= limit; i++)
isPrimeBruteForce(i);
end = clock();
time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("暴力法耗時: %.6f 秒\n", time_used);

// 測試 sqrt(n) 優化
start = clock();
for (int i = 2; i <= limit; i++)
isPrimeOptimized(i);
end = clock();
time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("sqrt(n) 優化耗時: %.6f 秒\n", time_used);

return 0;
}

輸出:

暴力法耗時: 76.019764
sqrt(n) 優化耗時: 0.276063

總結來說,演算法是一組明確的步驟(指令),用來解決特定問題。其本質為解決問題的方法。

而好的演算法可以讓程式執行更快,這也是我們所追求的。

留言
avatar-img
留言分享你的想法!
avatar-img
電資鼠 - 您的學習好夥伴
9會員
215內容數
在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
2025/03/09
雙向串列 (Double Linked List, DLL) 是一種鏈結資料結構,本章節將以完整註解,搭配關鍵操作地方的圖示輔助學習,讓你輕鬆搞懂複雜觀念,並透過C語言實作。
Thumbnail
2025/03/09
雙向串列 (Double Linked List, DLL) 是一種鏈結資料結構,本章節將以完整註解,搭配關鍵操作地方的圖示輔助學習,讓你輕鬆搞懂複雜觀念,並透過C語言實作。
Thumbnail
2025/03/08
環狀鏈結串列是一種特殊的鏈結串列,其最後一個節點的指標指向第一個節點,而非 NULL,形成一個循環結構。本章節將以豐富圖示,引導讀者了解環狀串列在各種地方執行插入和刪除節點的步驟,輕鬆學會資工科的專業知識-環狀串列。
Thumbnail
2025/03/08
環狀鏈結串列是一種特殊的鏈結串列,其最後一個節點的指標指向第一個節點,而非 NULL,形成一個循環結構。本章節將以豐富圖示,引導讀者了解環狀串列在各種地方執行插入和刪除節點的步驟,輕鬆學會資工科的專業知識-環狀串列。
Thumbnail
2025/03/07
本章節將探討右上三角稀疏矩陣。
Thumbnail
2025/03/07
本章節將探討右上三角稀疏矩陣。
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
介紹朋友新開的蝦皮選物店『10樓2選物店』,並分享方格子與蝦皮合作的分潤計畫,註冊流程簡單,0成本、無綁約,推薦給想增加收入的讀者。
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元二次方程式
Thumbnail
中學數學基礎練習—一元二次方程式
Thumbnail
中學數學基礎練習—一元二次方程式
Thumbnail
中學數學基礎練習—一元二次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
中學數學基礎練習—一元一次方程式
Thumbnail
高中數學主題練習—對數方程式
Thumbnail
高中數學主題練習—對數方程式
Thumbnail
演算法映射化簡的核心觀念 在面對新題目的時候,除了重頭想一個新的演算法之外; 還有另一個方法,想看看有沒有核心觀念彼此相同的問題與演算法, 如果有,就可以把新的題目映射化簡到已知解法的問題,用已知的演算法去解開。 接著,我們會介紹幾個範例,並且使用映射化簡的技巧來解題,透過化
Thumbnail
演算法映射化簡的核心觀念 在面對新題目的時候,除了重頭想一個新的演算法之外; 還有另一個方法,想看看有沒有核心觀念彼此相同的問題與演算法, 如果有,就可以把新的題目映射化簡到已知解法的問題,用已知的演算法去解開。 接著,我們會介紹幾個範例,並且使用映射化簡的技巧來解題,透過化
Thumbnail
最近有新的訂閱者加入, 想趁這個機會再分享一次學習心法與建議給第一次練習的讀者、同學們。 如果你本身已經很熟練演算法,那隨機挑題目練習ok,可以測試觀念是否正確,並且驗證寫code的效率與正確程度。 如果是剛畢業或還在學,以前沒有打過程式競賽。 想開始有系統地增強演算法&資料結構的能力
Thumbnail
最近有新的訂閱者加入, 想趁這個機會再分享一次學習心法與建議給第一次練習的讀者、同學們。 如果你本身已經很熟練演算法,那隨機挑題目練習ok,可以測試觀念是否正確,並且驗證寫code的效率與正確程度。 如果是剛畢業或還在學,以前沒有打過程式競賽。 想開始有系統地增強演算法&資料結構的能力
Thumbnail
解決電腦上遇到的問題、證明正確性、探討效率 並且很著重溝通,說服別人你做的事是正確且有效率的。 內容: 計算模型、資料結構介紹、演算法介紹、時間複雜度介紹。
Thumbnail
解決電腦上遇到的問題、證明正確性、探討效率 並且很著重溝通,說服別人你做的事是正確且有效率的。 內容: 計算模型、資料結構介紹、演算法介紹、時間複雜度介紹。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News