演算法 | Big O 複雜度| Pseudocode 偽代碼

更新於 發佈於 閱讀時間約 11 分鐘
演算法是一種解決問題的虛擬邏輯。

想像一下,今天要在字典裡面找到 Zoo,有幾種方法:

  • 逐頁查找:如果字典有 1000 頁,最糟情況下需要翻 1000 次 才能找到。
  • 兩頁兩頁找:這樣的話,1000 頁最多要翻 500 次。
  • 二分查找:從字典的中間開始,假設翻到 M,而 Z 在 M 之後,這時可以忽略掉左邊的資料。使用這種方法,1000 頁只需要翻大約 10 次(對數操作,log₂1000 ≈ 10)。

這三種方法都可以成功找到「Zoo」,但哪一種是效率最高的呢?

同樣地,程式也可以正確運行,但如何讓它效率更高呢?其中一個衡量標準是時間複雜度。透過理解時間複雜度,我們可以有標準評估程式的優劣。

Big O 表示法是時間複雜度的常用符號,也是軟體工程師應具備的基本知識之一。

時間複雜度

「時間複雜度」用來表示一個演算法隨著輸入大小(通常記作 n)增長時,運行所需的步驟數的變化。時間複雜度主要是用 O( ) 即 Big O 表示法來表達。

O(n) 念作 O of n,雖然有時可能會遇到像 O(n/2) 這樣的情況,但常數倍數(如 /2)在 Big O 表示法中並不影響複雜度的大小,因為對演算法的整體速度影響不大。因此,通常省略常數,直接用 O(n) 表示。

Big O 用來表示演算法在最壞情況下的時間複雜度上限,描述的是隨著資料量增大,運行步驟增長的趨勢。

例子:1 加到 100 如果使用迴圈來計算 1 加到 100,電腦就需要執行 99 次。如果是加到 1000,則需要執行 999 次,因此這是一個 O(n) 的演算法。而如果使用公式 [(1+100)∗100]/2,這只需要固定的 3 個步驟(加、乘、除),不管數字多大,因此這是一個 O(1) 的演算法。


各種時間複雜度的解釋:

  1. O(n²): 如果有 n 個資料,運行時間會是 n²(比如 n² 次運算)。常見於雙重巢狀迴圈,常用在處理圖像或是矩陣。
  2. O(log n): 如果有 n 個資料,運行時間是 log(n)。雖然技術上是 log₂(n),但底數(2、10)在 Big O 表示法中是可以忽略的,所以我們通常簡單寫作 O(log n)。一個典型的例子是二元搜尋。
  3. O(n): 如果有 n 個資料,運行時間與資料量呈線性關係,即每個資料都需要處理一次。這樣的演算法就屬於 O(n)。

在演算法的時間複雜度會忽略常數,且只看最高次項,因為最高次項對演算法的執行時間影響最大,而常數和係數的影響相對較小。例如:

5n2+3n+2

  • 5n是二次項,
  • 3n 是一次項,
  • 2 是常數項。

當我們分析時間複雜度時,我們會忽略常數 2 和低次項 3n,因為當 n 越來越大時,低次項就不重要。我們只會看最高次項 ,所以這個演算法的時間複雜度可以簡化為 O(n2)。

時間複雜度排序圖解

  • 最好的是綠色的 O(1),不管輸入數值多大,步驟固定不變。
  • 最差的是粉紅色的 O(n!),也就是階乘增長,隨著輸入數量 n 增長,程式跑的步驟數會迅速增加。
raw-image


補充 Big O、Big Ω 和 Big Θ:

  1. Big O:只關注演算法的上界,表示最大可能的運行時間。
  2. Big Ω:只關注演算法的下界,表示最小可能的運行時間。
  3. Big Θ:同時考慮上界和下界,表示演算法的精確時間複雜度,適用於上下界一致的情況。

** 注意:big O 可以代表所有上界,它是個範圍而不是定值,但我們只會取其最佳者。

raw-image

假設某演算法的時間複雜度,最差是 2最好是 n2 ,這張圖中,2的右邊都是 Big O,n2 的左邊都是 Big Ω

Big O 是最常用的,因為通常我們最關注演算法在上界的表現。

最後的總結:

Big O 表示法常用來描述演算法的最壞情況下的效率。雖然還有 Big Ω 和 Big Θ 這些表示法,但新手只需要記得 Big O 是用來分析時間複雜度的常見工具。在軟體工程師面試時會詢問「這種寫法的 Big O 是多少?」,並詢問有沒有更好的 Big O。

線型搜尋、二元搜尋的時間複雜度

線性搜尋(Linear)就是一頁一頁找

  • 最佳情況:O(1),第一格就找到。
  • 最糟情況:O(n),目標值在最後一格,要走過每筆資料才能找到。
  • 平均情況:O(n/2)=O(n)。但是數字大到可忽略 /2 的差異。
raw-image


二元搜尋(Binary search)

需要已排序的資料。直接從中間對半切,再根據該資料落在左邊或是右邊繼續找。

  • 最佳情況:O(1),切一次就找到。
  • 最糟情況:O(log2n),目標值在最後一格,要走過每筆資料才能找到。
  • 平均情況:O(1)+O(log2n) 約略等於 O(logn)。
raw-image



線性搜尋、二元搜尋程式碼

我一開始的寫法:

目的:一個一個讀,找到數字就回傳 found ,沒有就回傳 not found。

#include <cs50.h>
#include <stdio.h>

int main()
{
int number[] = {1, 20, 4, 25, 50, 100};
int n = get_int("Number: ");
for (int i = 0; i < 6; i++)
{
if (number[i] == n)
{
printf("Found\n");
}
else
printf("Not Found\n");
}
}

結果跑出:

raw-image

但我其實是需要只需要傳一次就好,要全部都讀完才告訴我有沒有。現在,再試一次另外一種寫法。

#include <cs50.h>
#include <stdio.h>

int main()
{
int number[] = {1, 20, 4, 25, 50, 100};
int n = get_int("Number: ");
for (int i = 0; i < 6; i++)
{
if (number[i] == n)
{
printf("Found\n");
}
}
printf("Not Found\n");
}

這次也同時跑出 FoundNot Found ,原因是不管程式前面如何運行,結果都會產生 Not Found

所以要使用 return 0 表示成功不再繼續運行;而 return 1 表示失敗。

#include <cs50.h>
#include <stdio.h>

int main()
{
int number[] = {1, 20, 4, 25, 50, 100};
int n = get_int("Number: ");
for (int i = 0; i < 6; i++)
{
if (number[i] == n)
{
printf("Found\n");
return 0; // 成功,不用再繼續跑
}
}
printf("Not Found\n");
return 1; // 失敗,找不到
}


Pseudocode 偽代碼

在正式寫出可以運行的程式之前,我們可以先從第一步到最後一步想好如何解決問題,並使用接近程式邏輯的方式來思考。這就像寫英文作文時,先用英文擬出大綱,再補充內容,最後調整成正確的文法。

偽代碼(pseudocode)有助於梳理邏輯思路。它不屬於任何特定的程式語言,因此無論用哪種語言,偽代碼都能幫助我們組織和規劃解決問題的步驟。當邏輯清晰後,再根據所選的程式語言進行細節調整。例如,思考如何進行 1 到 7 的迴圈時,可以先寫出偽代碼:

for i from 1 to 7: 
i++

這雖然不是正確的語法,但它幫助我們釐清迴圈的運作方式。而在實際的 C 語言中,這段偽代碼可以被改寫為:

for (int i = 0; i < 7; i++)

另外一個例子,我第一次寫 1 加到 100。可以先寫個步驟的思路再寫偽代碼:

  • sum 設為 0。
  • 使用 for 迴圈,從 i = 1 開始,直到 i = 100 結束。
  • 每次迴圈中,將目前的 i 值加到 sum 中,得到新的 sum 值。
  • 注意,以下偽代碼不能在程式運行,因為沒有標頭檔,和主程式 int main()。
int sum = 0; 

for (int i = 1; i <= 100; i++) {
sum = sum + i;
}

如果以 Python 的概念可以寫成:

sum = 0 

for i in range(1, 101):
sum += i

print(sum)

C Structures (structs)


假設我今天要建立「學生」的資料庫,這個學生有多種不同類型的資料需要儲存,比如姓名、年齡、學號和成績。這些資料的類型可能是字串(姓名)、整數(年齡)、浮點數(成績)。如果不用 Structures,可能需要為每一個資料建立一個變數,這會讓程式變得很複雜。結構可以能把這些相關的資料整合在一起,像是「打包」成一個資料包一樣,更方便工程師管理跟使用。至於詳細的應用會在下篇詳述。

補充資料

Big O 在面試的情境。

【工程師求職攻略】 面試流程大解析 找工作照著這5步 Coding Interview like a PRO!

誠徵資深實習生|面試過程公開




留言
avatar-img
留言分享你的想法!
Bicky-avatar-img
發文者
2024/10/10
P/NP 問題、NPC問題、停機問題、N皇后問題提及了這篇文章,趕快過去看看吧!
Bicky-avatar-img
發文者
2024/10/02
演算法 | 選擇排序 |氣泡排序 | 合併排序| 遞迴 提及了這篇文章,趕快過去看看吧!
avatar-img
越南放大鏡 X 下班資工系
13會員
60內容數
雙重身份:越南放大鏡 X 下班資工系 政大東南亞語言學系是我接觸越南語的起點,畢業後找越南外派工作的生活跟資訊時,發現幾乎都是清單式的分享,很難身歷其境。所以我希望「越南放大鏡」可以帶讀者看到更多細節和深入的觀察。 - 下班資工系則是自學資工系的課程內容,記錄實際操作的過程,學習理論的過程。希望可以跟讀者一起成長。
2025/04/24
本系列文章將循序漸進地介紹 JavaScript 的核心概念,從基礎語法到進階應用,例如非同步程式設計和 React 基礎。內容淺顯易懂,並使用生活化的比喻幫助讀者理解,搭配程式碼範例,適合 JavaScript 初學者學習。
Thumbnail
2025/04/24
本系列文章將循序漸進地介紹 JavaScript 的核心概念,從基礎語法到進階應用,例如非同步程式設計和 React 基礎。內容淺顯易懂,並使用生活化的比喻幫助讀者理解,搭配程式碼範例,適合 JavaScript 初學者學習。
Thumbnail
2025/04/21
本文介紹行動通訊網路的演進歷史,從1G到5G,並說明ITU與3GPP在制定通訊規格上的重要角色,以及5G的三大關鍵應用場景:URLLC、eMBB和mMTC。
Thumbnail
2025/04/21
本文介紹行動通訊網路的演進歷史,從1G到5G,並說明ITU與3GPP在制定通訊規格上的重要角色,以及5G的三大關鍵應用場景:URLLC、eMBB和mMTC。
Thumbnail
2025/04/11
這篇文章說明網路的七層模型、IP 位址、通訊埠、TCP/UDP 協定、HTTP 協定、HTTP 狀態碼以及 WebSocket,並解釋它們之間的關係與互動方式。文中包含許多圖表和範例,幫助讀者理解這些網路概念。
Thumbnail
2025/04/11
這篇文章說明網路的七層模型、IP 位址、通訊埠、TCP/UDP 協定、HTTP 協定、HTTP 狀態碼以及 WebSocket,並解釋它們之間的關係與互動方式。文中包含許多圖表和範例,幫助讀者理解這些網路概念。
Thumbnail
看更多
你可能也想看
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
演算法是一種解決問題的虛擬邏輯,他不像 C 語言有直接的程式碼,而是一種虛擬的問題解決方式。 想像一下,今天要在字典裡面找到 Zoo,有幾種方法: 逐頁查找:如果字典有 1000 頁,最糟情況下需要翻 1000 次 才能找到。 兩頁兩頁找:這樣的話,1000 頁最多要翻 500 次。 二分查
Thumbnail
演算法是一種解決問題的虛擬邏輯,他不像 C 語言有直接的程式碼,而是一種虛擬的問題解決方式。 想像一下,今天要在字典裡面找到 Zoo,有幾種方法: 逐頁查找:如果字典有 1000 頁,最糟情況下需要翻 1000 次 才能找到。 兩頁兩頁找:這樣的話,1000 頁最多要翻 500 次。 二分查
Thumbnail
題目敘述 386. Lexicographical Numbers 給定一個數字n,請實作一個字典序(Lexical order)排列的報數機, 依字典序輸出所有1~n的數字。 你必須實現一個O(n) time線性時間,O(1) extra space常數額外空間的演算法。
Thumbnail
題目敘述 386. Lexicographical Numbers 給定一個數字n,請實作一個字典序(Lexical order)排列的報數機, 依字典序輸出所有1~n的數字。 你必須實現一個O(n) time線性時間,O(1) extra space常數額外空間的演算法。
Thumbnail
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
Thumbnail
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
Thumbnail
三種做法所花的時間都不同,請試著一步步優化,在只跑一次迴圈下完成吧!
Thumbnail
三種做法所花的時間都不同,請試著一步步優化,在只跑一次迴圈下完成吧!
Thumbnail
題目會給定我們一個n值,問我們n! 也就是n階乘 尾巴的零有多少個? 例如n=5 就是代表5! = 5x4x3x2x1=120 尾巴有一個零,回傳1
Thumbnail
題目會給定我們一個n值,問我們n! 也就是n階乘 尾巴的零有多少個? 例如n=5 就是代表5! = 5x4x3x2x1=120 尾巴有一個零,回傳1
Thumbnail
題目會給定一個陣列,要求我們把裡面的數字依照奇偶數去排序, 偶數的排在前面,奇數的排在後面。
Thumbnail
題目會給定一個陣列,要求我們把裡面的數字依照奇偶數去排序, 偶數的排在前面,奇數的排在後面。
Thumbnail
題目會給我們一個排序好的陣列,還有一個目標值target 要求我們在陣列中尋找target所在的索引位置。 如果target 不存在,返回-1 題目要求必須在O( log n )對數時間內完成 。
Thumbnail
題目會給我們一個排序好的陣列,還有一個目標值target 要求我們在陣列中尋找target所在的索引位置。 如果target 不存在,返回-1 題目要求必須在O( log n )對數時間內完成 。
Thumbnail
以一個雜魚測試工程師的角度來看int應用場景
Thumbnail
以一個雜魚測試工程師的角度來看int應用場景
Thumbnail
假設有天你要在電話簿找一個K開頭的人,或是O開頭的人 你並不會從A開始找 一定是從最接近的開始找。 二分搜尋是一種演算法 下方是二分搜尋演算法的如何作用 STEP 1 圖一這是一組陣列,由小到大排列,其中我們在這陣列要找的數字是“13”所以我們必須把它存在 searchForNumber 這個變數裡
Thumbnail
假設有天你要在電話簿找一個K開頭的人,或是O開頭的人 你並不會從A開始找 一定是從最接近的開始找。 二分搜尋是一種演算法 下方是二分搜尋演算法的如何作用 STEP 1 圖一這是一組陣列,由小到大排列,其中我們在這陣列要找的數字是“13”所以我們必須把它存在 searchForNumber 這個變數裡
Thumbnail
座號是每一個學生擁有過的一個數字,但你有想過座號是怎麼排序的嗎? 座號的第一位通常都是姓氏筆畫最少的人如:丁、王等,那如果今天有兩個人都姓王的時候,會怎麼排序呢,當然最簡單的方式就是再比第二個字,那如果今天剛好三個字都一樣的話就會講求到資料的穩定性。 比較:
Thumbnail
座號是每一個學生擁有過的一個數字,但你有想過座號是怎麼排序的嗎? 座號的第一位通常都是姓氏筆畫最少的人如:丁、王等,那如果今天有兩個人都姓王的時候,會怎麼排序呢,當然最簡單的方式就是再比第二個字,那如果今天剛好三個字都一樣的話就會講求到資料的穩定性。 比較:
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News