該如何學好 "寫程式" ??

該如何學好 “寫程式” ??

問題與答案 (FAQ)

Q&A 類別 A: 概念理解類

A-Q1: 什麼是寫程式的「基本功」?

  • A簡: 基本功是資料結構、演算法與系統基礎的綜合能力,支撐你理解問題、正確建模並有效實作與除錯。
  • A詳: 基本功指掌握計算機概論、資料結構與演算法、作業系統與系統程式、再到 OOP/設計模式與工程方法(XP/TDD)。它讓你知道問題怎麼抽象、資料怎麼表示、操作的時間/空間成本、系統怎麼運轉。具備基本功,才能不依賴框架糖衣,迅速判斷技術可解與不可解的邊界,並在需求或工具改變時保持可遷移的能力。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q2, A-Q4, B-Q6

A-Q2: 為什麼學程式沒有「速成」?

  • A簡: 工具簡化操作,卻隱藏更多知識。缺基本功只能出招,無法理解原理與應變,遇新問題就卡關。
  • A詳: 工具與框架降低入門門檻,但背後的資料結構、演算法、系統與工程方法的知識量不減反增。速成只會學到表面的 API 與範例套路,缺少對邏輯、複雜度、記憶體、併發、錯誤處理等內功的理解,一旦情境偏離範例,效率與正確性都難保。因此投資基本功,是避免「只會照做、不會思考」的唯一路徑。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q1, A-Q3

A-Q3: 工具進步為何反更需要知識?

  • A簡: 工具抽象化提高效率,但也疊加更多層次。理解內層原理才能正確選用、調校與除錯。
  • A詳: 高階框架隱藏 I/O、記憶體、排程、GC、網路等細節,讓開發更快。但系統層次更多,互動更複雜,一旦出現效能瓶頸、資源爭用或非典型需求,必須能下鑽到原理層。懂抽象也懂實作,才能在需求、效能與可靠性間做正確折衝,避免「黑箱迷信」與過度工程化。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q1, A-Q2

A-Q4: 入門到進階的學習階段有哪些?

  • A簡: 三階段:資料結構/演算法;作業系統/系統程式;OOP/設計模式與工程方法(XP、TDD)。
  • A詳: 建議路徑:第一階段打好資料結構與演算法(陣列、串列、樹、雜湊、排序、搜尋與 Big-O)。第二階段理解作業系統與系統程式(程序、執行緒、排程、記憶體管理、I/O、系統呼叫),建立系統觀。第三階段學 OOP/設計模式(抽象、封裝、策略、工廠等)與工程方法(XP、TDD、重構),連結設計與開發流程,向架構與團隊協作邁進。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q1, A-Q5, B-Q20

A-Q5: Programmer、Software Engineer、Architect 有何差異?

  • A簡: Programmer重實作,Engineer掌系統面與工程方法,Architect負責抽象設計與技術決策。
  • A詳: Programmer專注把功能寫出來,需要良好資料結構與演算法基礎。Software Engineer需理解系統運作、可靠性、效能與工程流程,能做組件化、測試與部署。Architect強調抽象建模、系統劃分、設計模式與非功能性需求(可伸縮、可維護、安全),並做技術路線決策。三者是能力光譜而非身份標籤,隨基礎與廣度加深而演進。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q4, A-Q15, A-Q16

A-Q6: 什麼是資料結構?

  • A簡: 資料結構是資料的儲存與組織方式,影響操作效率與記憶體使用。
  • A詳: 資料結構定義如何表示資料與其關係,支援插入、刪除、搜尋、遍歷等操作。常見有陣列、鏈結串列、堆疊、佇列、雜湊表、樹與圖。選擇合適結構能大幅改善時間與空間效率,例如雜湊表近似 O(1) 查找,二元搜尋樹 O(log n) 有序操作。理解特性與適用場景是演算法設計與系統實作的基石。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q7, B-Q8, B-Q9

A-Q7: 為何要學習排序演算法?

  • A簡: 排序是通用基礎,訓練抽象能力、複雜度分析與資料操作技巧。
  • A詳: 排序問題普遍出現在報表、索引、搜尋、合併與資料清理。學習不同排序(Bubble、Quick、Merge、Heap)可理解比較次數、交換成本、穩定性、空間使用與快取友善性,並練習以 Big-O 推估效率與選擇策略。更重要的是借此練習將口語流程轉為可執行步驟,建立演算法思維。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q6, B-Q7, C-Q1, C-Q2

A-Q8: 什麼是時間複雜度(Big-O)?

  • A簡: Big-O 描述輸入規模增長下演算法執行時間的上界級數。
  • A詳: 時間複雜度用 O(1)、O(log n)、O(n)、O(n log n)、O(n^2) 等表示隨輸入 n 增加,步驟數如何成長。它忽略常數與低階項,聚焦趨勢比較,能幫助挑選資料結構與演算法、預估擴充上限與做效能預算。實務仍需實測,因常數、記憶體區域性與實作細節會影響實測結果。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q12, A-Q9

A-Q9: List 與 LinkedList 有何差異?

  • A簡: List 以連續陣列儲存,隨機存取快;LinkedList 以節點串接,插刪中間快。
  • A詳: List 內部是動態陣列,索引存取 O(1),尾端追加攤銷 O(1),中間插刪 O(n)。LinkedList 是雙向節點,插刪 O(1)(已得節點),但定位節點 O(n),且快取區域性差。小資料量差異不明顯;大量資料或頻繁中間插刪才考慮 LinkedList。多數情況 List 更實用且節省記憶體。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q14, C-Q5, D-Q6

A-Q10: Stack 與 Queue 有何差別與用途?

  • A簡: Stack 後進先出(LIFO),Queue 先進先出(FIFO),適用回溯與排程等情境。
  • A詳: Stack 用於函式呼叫、遞迴回溯、撤銷操作等;典型操作為 push/pop/peek。Queue 用於工作排程、廣度優先搜尋、訊息緩衝等;典型操作為 enqueue/dequeue。兩者皆可用陣列或鏈結串列實作,選擇視容量、併發與快取友善性。理解其行為有助於設計流程控制與圖搜尋策略。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q17, C-Q6

A-Q11: 什麼是 Hash Table?為何常用?

  • A簡: 以雜湊函式將鍵映射到桶位,提供近似 O(1) 查找與更新。
  • A詳: 雜湊表用 hash(key) 計算索引放入桶位(bucket)。碰撞可用鏈結串列(分離鏈結)或開放定址(線性/二次探測、雙雜湊)處理。當載入因子過高,需擴容再雜湊。典型應用為字典、索引、快取與去重。正確選函式與載入因子,能在大規模資料下維持穩定效率。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q9, C-Q3, C-Q4

A-Q12: 什麼是 Binary Tree(含 BST)?

  • A簡: 每節點最多兩子節點的樹。BST 維持左小右大,支援 O(log n) 搜尋。
  • A詳: 二元樹是一種階層結構,便於表示有序與分割。二元搜尋樹(BST)維持中序遞增序,搜尋、插入、刪除平均 O(log n);但若退化為鏈,最差 O(n)。平衡變體(AVL、紅黑樹)透過旋轉維持高度對數級。樹結構廣用於索引、語法樹與排程。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q10, B-Q11

A-Q13: 什麼是 Heap?常見用途?

  • A簡: 堆是一種近似完全二元樹,支援 O(log n) 插入與取出極值。
  • A詳: 最小堆維持每節點小於子節點,根為最小值;最大堆相反。以陣列表示,父子索引有固定關係。操作包含建堆、插入(上濾)、取出根(下濾)。適合實作優先序佇列、計算前 K 大/小、Dijkstra 的 frontier 管理與即時統計。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q11, B-Q16

A-Q14: 何謂穩定排序與就地排序?

  • A簡: 穩定排序保持相等鍵的原相對次序;就地排序使用常數額外空間。
  • A詳: 穩定性影響多鍵排序與相等鍵的可預期性;如 Merge Sort 穩定,Quick Sort 非穩定(可做變體)。就地(in-place)排序如 Quick/Heap 在空間有限時有優勢。選擇時需權衡穩定性、時間與空間,並配合資料分佈與快取行為。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q19, C-Q1, C-Q2

A-Q15: OOP 的核心價值是什麼?

  • A簡: 以抽象、封裝、繼承、多型組織複雜度,讓設計更可維護與可重用。
  • A詳: OOP 提供以物件建模問題域的方式,藉由封裝隱藏實作、以介面暴露行為,利用多型替換實作,降低耦合。配合設計模式(策略、工廠、觀察者等)可管理變動與擴充。其價值在於清晰邊界、降低複雜度與提升可測試性。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q16, B-Q20

A-Q16: 設計模式的目的與價值是什麼?

  • A簡: 提供可重複的設計解法語彙,應對變動、複用與複雜度管理。
  • A詳: 設計模式是針對常見設計問題的抽象解法集合,讓團隊能以共同語言溝通結構與責任分配。如策略解耦演算法、工廠隔離建構、裝飾器動態擴充行為。模式不是銀彈,需從需求變動點出發,避免過度設計。與 TDD/重構結合更能落地。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q15, C-Q10

A-Q17: 為何需要作業系統與系統程式基礎?

  • A簡: 理解程序、記憶體、I/O、排程與系統呼叫,才能寫出高效可靠的軟體。
  • A詳: 作業系統決定程式如何獲得 CPU 時間、如何配置與回收記憶體、如何進行 I/O 與併發。系統程式涵蓋編譯器、連結器、執行時、庫與介面。掌握這些,能在效能問題、資源限制與跨平台時做正確決策,避免以為「框架會自動幫你搞定一切」的誤解。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q3, B-Q4, B-Q5

A-Q18: 為何要學 XP/TDD?

  • A簡: 以短迭代、測試先行與重構,降低風險,讓設計逐步演進且可驗證。
  • A詳: XP 強調持續整合、結對、簡單設計;TDD 則以 Red-Green-Refactor 節奏推動需求澄清與設計內聚。對演算法與資料結構,TDD 有助邊界條件與退化情境的驗證,建立可回歸的安全網,支持持續優化與重構,避免技術債堆積。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q20, C-Q7

A-Q19: 為何框架與工具不能取代內功?

  • A簡: 工具解決「怎麼做」,內功決定「做得對與做得好」,面對新問題能自我生成解法。
  • A詳: 框架提供抽象,但抽象有邊界。超出邊界或遇到效能與錯誤時,需要理解底層原理與演算法才能修正或延伸。內功讓你評估權衡、選擇適當資料結構與設計,避免盲從潮流或過度工程化。面對技術變遷,內功是最可遷移的資產。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q1, A-Q3

A-Q20: 什麼是程式設計的「邏輯能力」?

  • A簡: 將問題分解、建立正確流程與不變量,選擇合適資料結構與演算法解題。
  • A詳: 邏輯能力包含抽象建模、流程設計、嚴謹推理與驗證。能識別資料與操作的關係、維持不變量(如 BST 性質)、定義邊界條件與例外處理,並以測試與推導驗證正確性。這是跨語言可遷移的核心能力,比 API 記憶更重要。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q6, C-Q6

Q&A 類別 B: 技術原理類

B-Q1: 程式從輸入到輸出如何運作?

  • A簡: 程式碼經編譯/解譯交由作業系統載入,CPU 執行指令,透過記憶體與 I/O 完成輸入輸出。
  • A詳: 原理: 原始碼→編譯/解譯→機器碼/位元碼。流程: 程式載入→配置堆疊/堆→CPU 取指-譯碼-執行→系統呼叫進行 I/O→輸出。組件: 編譯器/執行時、作業系統(排程/記憶體)、CPU、記憶體、I/O 裝置。理解此鏈路可定位效能瓶頸與錯誤來源。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q3, B-Q2, B-Q3

B-Q2: CPU 如何執行指令並影響效能?

  • A簡: CPU 以取指、譯碼、執行循環運作,受快取、分支預測與流水線影響效能。
  • A詳: 原理: 指令流水線並行化多階段,快取層級(L1/L2/L3)降低記憶體延遲。流程: 取指→譯碼→執行→寫回;分支錯判會清空流水線。組件: ALU、快取、分支預測器、記憶體控制器。演算法的資料區域性與分支規律性,將直接影響實測速度。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q1, B-Q13

B-Q3: 作業系統如何管理記憶體?

  • A簡: 以虛擬記憶體提供位址空間,透過分頁/分段與配置策略管理堆疊與堆。
  • A詳: 原理: 虛擬位址映射到實體記憶體/儲存,頁表與 TLB 加速查詢。流程: 配置→存取→缺頁→置換。組件: 分頁機制、配置器(小物件/大物件區)、GC 或手動回收。理解配置成本與區域性有助於資料結構選擇與避免碎片/溢出。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q17, D-Q7

B-Q4: 作業系統行程/執行緒排程如何影響程式?

  • A簡: 排程決定 CPU 配額與切換時機,影響延遲與吞吐,受 I/O 與同步影響。
  • A詳: 原理: 時間片輪轉、優先序、I/O 密集/CPU 密集分類。流程: 就緒→執行→阻塞→喚醒→搶佔。組件: 排程器、同步原語(鎖、事件)、中斷。對演算法測量需隔離併發干擾,對系統設計需考慮競爭與鎖競爭成本。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q17

B-Q5: 垃圾回收(GC)如何運作?

  • A簡: GC 追蹤存活物件並回收不可達,代數設計優化短命物件,回收時可能暫停。
  • A詳: 原理: 可達性分析(mark-sweep/compact),分代假設多數物件短命。流程: 分配→Minor GC→晉升→Major/Full GC→壓縮。組件: 配置器、寫屏障、停頓與並行回收。大量臨時配置會放大 GC 成本,影響尾延遲,需優化配置與物件壽命。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: D-Q9, B-Q3

B-Q6: Bubble Sort 如何運作?

  • A簡: 反覆比較相鄰元素並交換,把最大(或最小)值逐步「冒泡」至端點。
  • A詳: 原理: 比較交換排序,穩定、就地,時間 O(n^2)。流程: 外圈控制趟數,內圈相鄰比較,無交換時提前結束。組件: 兩層迴圈、交換函式、最佳化旗標。適用於小資料或教學練習,不建議大量資料使用。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q7, C-Q1

B-Q7: Quick Sort 如何運作?

  • A簡: 選樞紐分區,小於在左大於在右,對子區遞迴排序,平均 O(n log n)。
  • A詳: 原理: 分治法,非穩定、就地。流程: 選 pivot→分割(Hoare/Lomuto)→遞迴左右;退化時 O(n^2)。組件: 選樞策略(中位數/三取樣)、分割函式、尾遞迴最佳化。實務應對近排序資料採取隨機化或三取樣降低退化機率。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q7, C-Q2, D-Q2

B-Q8: Linked List 的基本操作原理是什麼?

  • A簡: 以節點記錄值與指標,透過調整指標插刪,搜尋需遍歷。
  • A詳: 原理: 節點包含 value、next(與 prev),非連續記憶體。流程: 插入/刪除 O(1)(已定位),搜尋 O(n)。組件: 節點結構、頭尾指標、迭代器。適合頻繁插刪但隨機存取少的場景,需注意快取不友善與額外指標開銷。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q6, A-Q9

B-Q9: Hash Table 的雜湊與碰撞處理機制?

  • A簡: 算雜湊值定位桶位,碰撞用鏈結或開放定址,維持載入因子並擴容。
  • A詳: 原理: hash(key)→index,均勻分佈降低碰撞。流程: 插入→檢桶→處理碰撞→必要時 rehash。組件: 雜湊函式、桶陣列、碰撞策略、載入因子門檻。設計不良會退化至 O(n)。鍵不可變且良好散佈是關鍵。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q11, C-Q3, D-Q4

B-Q10: 二元搜尋樹(BST)運作機制?

  • A簡: 維持左小右大不變量,搜尋/插入/刪除平均 O(log n),需處理平衡。
  • A詳: 原理: 中序為遞增。流程: 搜尋沿鍵比較向左/右;插入在葉;刪除分三情況(葉、單子、雙子需找前驅/後繼)。組件: 節點、旋轉(平衡樹)、不變量檢查。對於頻繁動態有序資料,平衡變體更合適。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q12

B-Q11: Heap 的建堆與取出流程?

  • A簡: 以陣列表示近完全樹,插入上濾、取根下濾,支援優先序操作。
  • A詳: 原理: 堆序性保證父子關係。流程: 建堆(自底向上 O(n))、插入(bubble up)、Extract-Root(bubble down)。組件: 陣列儲存、比較器、索引計算。常用於即時前 K 問題與最短路徑演算法的 frontier。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q13, B-Q16

B-Q12: 如何推導與比較時間複雜度?

  • A簡: 以基本操作次數表示為 n 的函數,取最高階與常數略化,比較成長趨勢。
  • A詳: 原理: 抽象成步驟數函式 T(n)。流程: 數學求和、遞迴式主定理、分攤分析。組件: 最佳/平均/最差界、實測常數。推導後仍需以效能剖析驗證,避免僅依理論選型。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q8, D-Q8

B-Q13: 陣列與鏈結串列的記憶體與快取行為?

  • A簡: 陣列連續且快取友善;鏈結串列分散指標多,遍歷較慢。
  • A詳: 原理: CPU 快取預取連續位址。流程: 遍歷陣列常命中快取,鏈結串列因隨機指標跳躍造成快取失誤。組件: 快取行為、指標開銷、記憶體配置器。影響實測與理論差距,常使 O(n) 與 O(n) 中陣列版本顯著更快。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q2, A-Q9

B-Q14: .NET List 與 LinkedList 的內部差異?

  • A簡: List 是動態陣列,擴容倍增;LinkedList 是雙向節點,節點含指標。
  • A詳: 原理: List 容量不足時 realloc 複製;LinkedList 透過節點串接。流程: List 索引 O(1)、插刪 O(n);LinkedList 插刪 O(1)(已定位)、索引 O(n)。組件: 內部陣列/節點類、Enumerator、版本戳。實務多選 List,除非明確需要 O(1) 中間插刪。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q9, C-Q5

B-Q15: 路徑規劃的圖表示法有哪些?

  • A簡: 以節點代表交流道,邊代表道路,權重為距離/時間,用鄰接表或矩陣表示。
  • A詳: 原理: 圖 G(V,E) 描述連通關係。流程: 建模→選表示→加權→選演算法。組件: 鄰接表(稀疏圖)、鄰接矩陣(稠密圖)、邊權與方向。對高速公路多為稀疏圖,鄰接表更節省記憶體並適合 Dijkstra。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q6, B-Q16

B-Q16: Dijkstra 演算法如何找最短路徑?

  • A簡: 以最小距離未確定點擴張,鬆弛鄰邊,透過優先佇列維護 frontier。
  • A詳: 原理: 貪婪策略,僅適用非負權。流程: 初始化距離∞、起點0→重複:取最小距離節點→鬆弛鄰邊→更新佇列,直到終點固定或佇列空。組件: 優先佇列(堆)、距離陣列、前驅記錄、訪問集合。回溯前驅得到路徑,權重可用距離或時間。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q11, B-Q15, C-Q6

B-Q17: BFS 與 DFS 如何運作?何時使用?

  • A簡: BFS 用佇列逐層擴張(最短邊數);DFS 用堆疊深入回溯(遍歷/偵測環)。
  • A詳: 原理: BFS 保證無權圖最短步數;DFS 適合拓撲排序、連通分量。流程: BFS:enqueue 起點→出佇列擴張;DFS:push→遞迴/迴圈回溯。組件: Queue/Stack、訪問標記、前驅。路徑權重非負且加權時用 Dijkstra,非加權可用 BFS。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q10, C-Q6

B-Q18: 二分搜尋如何運作?

  • A簡: 在已排序陣列中,反覆折半縮小範圍,時間 O(log n)。
  • A詳: 原理: 利用有序性比較中點。流程: 設 low/high→迴圈計 mid→比較決定移動邊界→直到找到或範圍空。組件: 有序資料、邊界處理、溢位安全的 mid 計算。常用於索引查找與前綴界限定位(lower/upper bound)。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: C-Q4, D-Q3

B-Q19: 演算法穩定性與就地排序的機制?

  • A簡: 穩定性靠比較與交換策略;就地靠在原陣列內移動元素與分區。
  • A詳: 原理: 穩定排序避免相等鍵跨越;就地排序節省空間。流程: Merge Sort 需輔助空間(可做 in-place 變體成本高);Quick Sort 以分區原地交換。組件: 比較器、分區函式、輔助緩衝。選型需配合資料特性與記憶體限制。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q14, C-Q1, C-Q2

B-Q20: TDD 的技術流程與在演算法中的應用?

  • A簡: 以測試驅動實作(紅-綠-重構),小步前進,確保正確性與設計品質。
  • A詳: 原理: 先寫失敗測試鎖定需求,再最小實作通過,最後重構。流程: 撰寫案例→實作→重構→循環。組件: 測試框架、斷言、測試資料/性質測試。在演算法中,特別適合邊界條件、退化資料與隨機化策略的驗證,提供回歸安全網。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q18, C-Q7

Q&A 類別 C: 實作應用類

C-Q1: 如何實作 Bubble Sort(C#)?

  • A簡: 兩層迴圈比較相鄰元素,必要時交換,加入早停旗標提升效率。
  • A詳: 步驟: 1) 外圈 0..n-2;2) 內圈 0..n-2-i 比較 arr[j] 與 arr[j+1];3) 若逆序交換;4) 若一趟無交換則提前結束。程式碼: C#: int[] Bubble(int[] a){ for(int i=0;i<a.Length-1;i++){ bool swapped=false; for(int j=0;j<a.Length-1-i;j++) if(a[j]>a[j+1]){(a[j],a[j+1])=(a[j+1],a[j]); swapped=true;} if(!swapped) break;} return a;} 注意: 就地操作;適合小規模或教學。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q6, A-Q14

C-Q2: 如何實作 Quick Sort(C#)?

  • A簡: 選樞紐分區後遞迴左右區間,採三取樣或隨機化降低退化風險。
  • A詳: 步驟: 1) 選 pivot(如三取樣);2) 分區(Lomuto/Hoare);3) 遞迴排序左右;4) 小區間可改插入排序。程式碼: C#: void Quick(int[] a,int l,int r){ if(l>=r) return; int i=l,j=r,p=a[(l+r)/2]; while(i<=j){ while(a[i]<p)i++; while(a[j]>p)j–; if(i<=j){(a[i],a[j])=(a[j],a[i]); i++; j–; } } if(l<j) Quick(a,l,j); if(i<r) Quick(a,i,r);} 注意: 避免最差 O(n^2),遞迴深度管控。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q7, B-Q19, D-Q2

C-Q3: 如何實作簡單 Hash Table(開放定址)?

  • A簡: 用陣列存鍵值,雜湊定位,碰撞以線性探測處理,適時擴容再雜湊。
  • A詳: 步驟: 1) 定義容量與載入因子;2) hash(key)%cap 定位;3) 若占用則 i=(i+1)%cap;4) 插入/查找/刪除標記懶刪。程式碼: C#: class OpenHash{ (string key,int val,bool used,bool tomb)[] t; int n; int Put(string k,int v){ if((double)n/t.Length>0.7) Rehash(); int i=Idx(k); for(;t[i].used&&!t[i].tomb&&t[i].key!=k;i=(i+1)%t.Length){} t[i]=(k,v,true,false); n++; return v;} /* 省略 Get/Del/Hash */ } 注意: 載入因子控制、刪除標記避免探測鏈斷裂。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q9, D-Q4

C-Q4: 如何在記憶體中快速查 100 萬筆通訊錄?

  • A簡: 以 Dictionary 做主鍵索引,必要時輔以排序陣列+二分搜尋支援範圍/前綴查詢。
  • A詳: 步驟: 1) 讀檔串流;2) 預估容量 new Dictionary(capacity);3) 主鍵→物件;4) 需前綴時建立排序清單供二分。程式碼: C#: var dict=new Dictionary<string,Contact>(1_500_000); foreach(var line in File.ReadLines(path)){ var c=Parse(line); dict[c.Id]=c; } // 前綴可用 SortedList 或自建鍵陣列+BinarySearch 注意: 避免裝箱/多餘配置,分批載入與監控記憶體。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q18, D-Q3

C-Q5: 如何量測 List 與 LinkedList 效能差異?

  • A簡: 以 Stopwatch 設計相同工作量情境,測試插入中間、尾插與遍歷時間。
  • A詳: 步驟: 1) 準備 N 與重複次數;2) 插入中間/尾插/搜尋;3) 去除 JIT 暖機偏差;4) 紀錄平均/中位數。程式碼: C#: var sw=Stopwatch.StartNew(); var list=new List(); for(int i=0;i<N;i++) list.Insert(list.Count/2,i); sw.Stop(); Console.WriteLine(sw.Elapsed); // LinkedList 同步測 注意: 測量隔離 GC/其他負載,重複多次取統計。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: A-Q9, B-Q14, D-Q6

C-Q6: 如何以圖與 Dijkstra 規劃高速公路路線?

  • A簡: 以交流道為節點、道路為加權邊,使用最小堆優先佇列執行 Dijkstra,回溯前驅得路徑。
  • A詳: 步驟: 1) 建鄰接表 Graph[int]→List<(to,weight)>;2) 跑 Dijkstra;3) 回溯 prev 得路徑。程式碼: C#: List Path(int s,int t){ var dist=Init(); var prev=new int[n]; var pq=new PriorityQueue<int,double>(); dist[s]=0; pq.Enqueue(s,0); while(pq.TryDequeue(out var u,out _)){ if(u==t) break; foreach(var (v,w) in G[u]) if(dist[u]+w<dist[v]){ dist[v]=dist[u]+w; prev[v]=u; pq.Enqueue(v,dist[v]); } } return Reconstruct(prev,t); } 注意: 權重非負,資料清理與節點映射。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q15, B-Q16

C-Q7: 如何以 TDD 開發排序函式?

  • A簡: 先寫測試(空陣列、單元素、重複、已排序/逆序),再最小實作,重構與擴充。
  • A詳: 步驟: 1) 建立專案與測試框架;2) 撰寫失敗測試;3) 實作通過;4) 重構抽取比較器;5) 新增隨機/大樣本測試。程式碼: C# (xUnit): [Fact] void Sort_Basic(){ var a=new[]{3,1,2}; Sort(a); Assert.Equal(new[]{1,2,3},a);} 注意: 加入極端與性能上限測試,確保行為穩定。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: B-Q20, A-Q18

C-Q8: 如何設計大型資料載入的初始化流程?

  • A簡: 串流讀取、預先配置容量、結構化解析,避免中間物件與不必要複製。
  • A詳: 步驟: 1) File.ReadLines 流式讀;2) 預估容量 new List/Dictionary(cap);3) 自訂 Parser 直寫結構;4) 分批提交與監控記憶體。程式碼: C#: using var fs=File.OpenRead(p); using var sr=new StreamReader(fs); var dict=new Dictionary<string,Contact>(1_200_000); string? line; while((line=sr.ReadLine())!=null){ var c=Parse(line,span:true); dict[c.Id]=c; } 注意: 避免 string 分割過度,考慮 Span/Memory。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q3, D-Q7

C-Q9: 如何優化查找以降低 GC 與提升快取命中?

  • A簡: 降低配置、使用結構與陣列、重用緩衝與池化,避免裝箱與臨時集合。
  • A詳: 步驟: 1) 使用 struct/陣列;2) ArrayPool/物件池;3) 扁平化資料;4) 批次處理降低函式呼叫。程式碼: C#: var pool=ArrayPool.Shared; var buf=pool.Rent(4096); try{ /* use */ } finally{ pool.Return(buf); } 注意: 測量前後 GC 與 CPU;留意結構複製與裝箱。
  • 難度: 高級
  • 學習階段: 進階
  • 關聯概念: B-Q5, B-Q13, D-Q9

C-Q10: 如何將演算法封裝成可重用元件?

  • A簡: 定義介面與策略,分離資料與行為,提供比較器與擴充點,搭配測試與文件。
  • A詳: 步驟: 1) 定義 ISorter 等介面;2) 以策略模式注入比較器;3) 提供純函式與就地版本;4) NuGet 封裝與 CI/CD。程式碼: C#: public interface ISorter{ void Sort(Span data, IComparer cmp); } public sealed class QuickSorter:ISorter{ /* ... */ } 注意: API 穩定性、相容性與版本化,附上基準測試。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: A-Q16, B-Q19

Q&A 類別 D: 問題解決類

D-Q1: Bubble Sort 排序結果錯誤怎麼辦?

  • A簡: 檢查比較方向、內外迴圈範圍與交換邏輯,加入無交換提前結束檢查。
  • A詳: 症狀: 局部逆序或未完全排序。原因: 內圈界限錯、比較方向顛倒、漏交換。解法: 審視邊界 j<a.Length-1-i、測試小樣本、加入 swapped 旗標。預防: 單元測試覆蓋空/單/重複/已序/逆序,程式碼審查關注邏輯。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: C-Q1, B-Q6

D-Q2: Quick Sort 遞迴過深 StackOverflow 怎麼辦?

  • A簡: 使用隨機/三取樣樞紐、先遞迴較小區間並改大區間為迭代,或設定遞迴深度上限。
  • A詳: 症狀: 大量重複或近序列導致最差分割。原因: 壞樞紐選擇、偏斜分割。解法: 隨機化、三取樣;尾遞迴最佳化;混合插入排序處理小區間。預防: 對極端資料加測試,提供非遞迴版本。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q2, B-Q7

D-Q3: 查 100 萬筆資料效能不佳原因?

  • A簡: 使用線性搜尋或未索引、資料結構選擇不當、未預配置容量導致擴容頻繁。
  • A詳: 症狀: 查詢延遲高、CPU 飆升。原因: List.IndexOf O(n)、字典載入因子高、擴容與 GC 開銷。解法: 用 Dictionary/HashSet,預設容量、良好雜湊鍵;範圍查詢建有序索引+二分。預防: 以 Big-O 預估+基準測試驗證。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q4, B-Q18

D-Q4: Hash Table 碰撞嚴重怎麼診斷與修正?

  • A簡: 檢查雜湊函式分佈與載入因子,啟用擴容或改為分離鏈結,避免不良鍵設計。
  • A詳: 症狀: 插入/查找退化到 O(n)。原因: 雜湊集中、容量過小、鍵可變導致值改變。解法: 改良雜湊、增大容量、降低載入因子、改鏈結策略。預防: 鍵不可變、監控碰撞率、壓測不同鍵分佈。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q3, B-Q9

D-Q5: 路徑規劃回傳非最短路徑怎麼辦?

  • A簡: 確認權重正確、邊雙向性與 Dijkstra 實作(鬆弛與前驅)正確,避免負權重。
  • A詳: 症狀: 路徑長度偏大或不連通。原因: 權重錯、漏邊、鬆弛條件錯、未使用最小堆。解法: 對小圖手算比對、記錄鬆弛日誌、驗證前驅回溯。預防: 單元測試涵蓋環/多路徑、資料建模審查。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q6, B-Q16

D-Q6: 為何改用 LinkedList 反而更慢?

  • A簡: 隨機存取與遍歷快取不友善、定位成本 O(n),實測常不如陣列型 List。
  • A詳: 症狀: 插刪快但整體變慢。原因: 快取失誤、節點額外記憶體、需先定位節點。解法: 僅在已定位節點大量插刪才用 LinkedList;否則用 List 或分塊結構。預防: 以實測資料與模式選型,不憑理論印象。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: C-Q5, B-Q14

D-Q7: 大量載入時 OutOfMemory 如何處理?

  • A簡: 64 位元、串流處理、分批載入、結構化資料與壓縮儲存,降低物件與字串碎片。
  • A詳: 症狀: 載入崩潰或 GC 頻繁。原因: 一次性讀入、過多暫存物件、字串分割。解法: 流式讀、預估容量、使用 struct/Span、池化緩衝、壓縮或記憶體映射。預防: 監測記憶體輪廓、設計資料格式與壓縮策略。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: C-Q8, B-Q3

D-Q8: Big-O 推估與實測差距大怎麼辦?

  • A簡: 常數/快取/分支/GC 影響巨大,需基準測試、剖析與資料特性分析。
  • A詳: 症狀: 理論快、實測慢。原因: 常數因子、記憶體區域性差、分支錯判、配置開銷。解法: 使用 Benchmark 工具、剖析熱點、換資料結構、改善區域性。預防: 先估再測、資料分佈檢視、建立性能預算。
  • 難度: 中級
  • 學習階段: 核心
  • 關聯概念: B-Q12, B-Q13

D-Q9: GC 暫停造成尾延遲如何改善?

  • A簡: 減少配置與晉升、使用池化與結構,調整代數與分配策略,平滑化負載。
  • A詳: 症狀: 間歇性延遲尖峰。原因: 大量暫時物件、LOH 分配、Full GC。解法: 降低配置、重用緩衝、Batch 處理、避免 boxing;必要時調整 GC 模式。預防: 設計階段評估物件壽命、建立配置指標與警戒線。
  • 難度: 高級
  • 學習階段: 進階
  • 關聯概念: C-Q9, B-Q5

D-Q10: 單元測試覆蓋不到邊界條件怎麼辦?

  • A簡: 加入性質測試與邊界集、隨機化與極值資料,明確列出不可變條件與預期。
  • A詳: 症狀: 發布後出現未預期輸入失敗。原因: 測試僅覆蓋常規情境。解法: 增加空/單/重複/排序/逆序、極大/極小與隨機測;用 property-based 測試建立不變量。預防: TDD 驅動邊界思考、審查測試案例充分性。
  • 難度: 初級
  • 學習階段: 基礎
  • 關聯概念: C-Q7, B-Q20

學習路徑索引

  • 初學者:建議先學習哪 15 題
    • A-Q1: 什麼是寫程式的「基本功」?
    • A-Q2: 為什麼學程式沒有「速成」?
    • A-Q3: 工具進步為何反更需要知識?
    • A-Q4: 入門到進階的學習階段有哪些?
    • A-Q6: 什麼是資料結構?
    • A-Q7: 為何要學習排序演算法?
    • A-Q8: 什麼是時間複雜度(Big-O)?
    • A-Q9: List 與 LinkedList 有何差異?
    • A-Q10: Stack 與 Queue 有何差別與用途?
    • B-Q6: Bubble Sort 如何運作?
    • C-Q1: 如何實作 Bubble Sort(C#)?
    • B-Q18: 二分搜尋如何運作?
    • C-Q5: 如何量測 List 與 LinkedList 效能差異?
    • A-Q19: 為何框架與工具不能取代內功?
    • A-Q20: 什麼是程式設計的「邏輯能力」?
  • 中級者:建議學習哪 20 題
    • B-Q7: Quick Sort 如何運作?
    • C-Q2: 如何實作 Quick Sort(C#)?
    • A-Q11: 什麼是 Hash Table?為何常用?
    • B-Q9: Hash Table 的雜湊與碰撞處理機制?
    • C-Q3: 如何實作簡單 Hash Table(開放定址)?
    • A-Q12: 什麼是 Binary Tree(含 BST)?
    • B-Q10: 二元搜尋樹(BST)運作機制?
    • A-Q13: 什麼是 Heap?常見用途?
    • B-Q11: Heap 的建堆與取出流程?
    • B-Q12: 如何推導與比較時間複雜度?
    • B-Q13: 陣列與鏈結串列的記憶體與快取行為?
    • C-Q4: 如何在記憶體中快速查 100 萬筆通訊錄?
    • A-Q14: 何謂穩定排序與就地排序?
    • B-Q19: 演算法穩定性與就地排序的機制?
    • A-Q18: 為何要學 XP/TDD?
    • B-Q20: TDD 的技術流程與在演算法中的應用?
    • C-Q7: 如何以 TDD 開發排序函式?
    • D-Q3: 查 100 萬筆資料效能不佳原因?
    • D-Q4: Hash Table 碰撞嚴重怎麼診斷與修正?
    • D-Q6: 為何改用 LinkedList 反而更慢?
  • 高級者:建議關注哪 15 題
    • A-Q5: Programmer、Software Engineer、Architect 有何差異?
    • A-Q15: OOP 的核心價值是什麼?
    • A-Q16: 設計模式的目的與價值是什麼?
    • A-Q17: 為何需要作業系統與系統程式基礎?
    • B-Q1: 程式從輸入到輸出如何運作?
    • B-Q2: CPU 如何執行指令並影響效能?
    • B-Q3: 作業系統如何管理記憶體?
    • B-Q15: 路徑規劃的圖表示法有哪些?
    • B-Q16: Dijkstra 演算法如何找最短路徑?
    • B-Q5: 垃圾回收(GC)如何運作?
    • C-Q6: 如何以圖與 Dijkstra 規劃高速公路路線?
    • C-Q9: 如何優化查找以降低 GC 與提升快取命中?
    • D-Q7: 大量載入時 OutOfMemory 如何處理?
    • D-Q8: Big-O 推估與實測差距大怎麼辦?
    • D-Q9: GC 暫停造成尾延遲如何改善?





Facebook Pages

AI Synthesis Contents

Edit Post (Pull Request)

Post Directory