---
# System prepended metadata

title: 8/13讀書會(開發工具、資料結構)
tags: [面試考古題]

---

# 8/13讀書會(開發工具、資料結構)
###### tags: `面試考古題` 資料結構

### Merge sort (合併排序法)

#### 時間複雜度：
- O(n log n)，執行時間會隨著以二為底的 log n 再乘上 n 增加

#### 基本步驟：
- 拆分
    1. 把大陣列切一半成為兩個小陣列
    2. 把切好的兩個小陣列再各自切一半
    3. 重複步驟二直到每個小陣列都只剩一個元素
- 合併
    1. 排序兩個只剩一個元素的小陣列並合併
    2. 把兩邊排序好的小陣列合併並排序成一個陣列
    3. 重複步驟二直到所有小陣列都合併成一個大陣列

![](https://i.imgur.com/XS7EzGw.png)

![](https://i.imgur.com/m2VUawj.gif)


#### 時間複雜度說明
- 拆分
    - 因為要把一個n的陣列拆分到每個小陣列只有一個數字，所以需要n-1個步驟
- 合併
    - 在合併兩個已經排序好的小陣列時，只需要比較第一個數字，把比較小的丟進新的陣列中，再重新比較兩個小陣列，所以合併n個數字，就需要n個步驟
    - 再者計算花了幾回合的合併，從一開始的7個陣列，合併完變4，再合併變2，最後合併成1個，每一回合的合併都讓下一回合少一半，所以是以2為底的log n次
    - **每回合合併步驟：O(n)**
    - **總花費回合數：O(log n)**

- 綜合 拆分 & 合併
    - (n - 1) + (n * log n)
    - 化成大 O 符號時，只計最高項係數並省略常數，因此合併排序法的時間複雜度，即為 O( n log n)

**Reference**
[JS 學資料結構與演算法 (排序篇) — 合併排序法 Merge Sort](https://oldmo860617.medium.com/js-%E5%AD%B8%E8%B3%87%E6%96%99%E7%B5%90%E6%A7%8B%E8%88%87%E6%BC%94%E7%AE%97%E6%B3%95-2-%E5%90%88%E4%BD%B5%E6%8E%92%E5%BA%8F%E6%B3%95-merge-sort-cf1a8457c9e0)
[初學者學演算法｜排序法進階：合併排序法](https://medium.com/appworks-school/%E5%88%9D%E5%AD%B8%E8%80%85%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-%E6%8E%92%E5%BA%8F%E6%B3%95%E9%80%B2%E9%9A%8E-%E5%90%88%E4%BD%B5%E6%8E%92%E5%BA%8F%E6%B3%95-6252651c6f7e)
[Repl](https://replit.com/@MarcoLin1/Merge-sort#index.js)

### Quick sort (快速排序)

#### 時間複雜度：
- 最好情況 O(n log n)，當所選的pivot剛好是中位數
- 最差情況 Ο(n2)，當所選的pivot每次都是最大or最小時
- 平均值 O(n log n)

#### 基本步驟：
- 從陣列中最後一個元素為基準，稱為pivot
- 目標：
    - 將序列中比pivot小的放左邊
    - 將序列中比pivot大的放右邊
- **調整數列(Partition)**
    - 功能：將數列區分成小於pivot和大於pivot兩半
    - 步驟
        - front為數列最前端的index，end為數列最尾端index
        - 初始化的i為 front - 1 (因為有可能所有數都比pivot大)，j為front
        - 當j的數值比pivot大，就j++
        - 當j的數值比pivot小，就i++，然後將i的數值和j的數值對調，再繼續j++
        - 一直持續上面步驟，直到j = end 代表都比較完，然後i++，將pivot與i的數值對調，此時左邊都是比pivot小的數值，右邊都是比pivot大
- 持續重複Partition到左右數列都沒有數值或只剩一個

![](https://i.imgur.com/W7n3uMw.png)

![](https://i.imgur.com/JALr4LC.png)


[Quick Sort快速排序法](http://alrightchiu.github.io/SecondRound/comparison-sort-quick-sortkuai-su-pai-xu-fa.html)
[JS 學資料結構與演算法 (排序篇)— 快速排序法 Quick Sort](https://oldmo860617.medium.com/js-%E5%AD%B8%E8%B3%87%E6%96%99%E7%B5%90%E6%A7%8B%E8%88%87%E6%BC%94%E7%AE%97%E6%B3%95-1-%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E6%B3%95-quick-sort-8904e226ad5d)

### What are some advantages/disadvantages to testing your code? 

測試種類：
1. 單元測試(unit testing)
    - 以程式碼的最小單位進行測試，保護程式邏輯不會在維護中被破壞
3. 整合測試(integration testing)
    - 整合多方資源進行測試，確保模組與模組間互動行為正確，讓不同模組各自開發維護過成中，不會因為功能調整而遭到破壞
5. 端對端測試(E2E testing) 
    - 從使用者角度出發，對真實系統進行測試，通常是人工測試，但也可以寫測試程式自動化

不建議寫測試的情況：
- **需求不確定**，因為當需求改變測試程式也要跟著改寫，開發成本增加
- **價值性不高**，網站價值性取決於經營者對價值的設定，因為測試需要時間，但時間就是金錢，如果沒有合理的時間寫測試，也就沒有撰寫測試的可能性

優點：
- 快速找到bug，節省開發成本
- 重構時能更快速且安全的解完成
- 確保code的品質
- 測試先行可以強迫開發者寫code前先做規劃
- 幫助開發者了解現有系統的功能
- 加快開發流程，避免開發完後還花時間修bug
- 可以記錄過程並且測試腳本可以重複使用

缺點：
- 開發者需要花更多時間寫更多複雜的code，有時候開發時程較短，就無法逐一寫測試
- 可以測試商業邏輯，但是比較難測試UI
- 測試無法抓出所有問題
- 如果程式重構的時候，大部分的testing code也要被翻新


### What is the purpose of a code style linting tool?

JavaScript是一個自由度高，但又是弱型別的語言，因此容易會有不經意的錯誤

Linting tool
- 主要目的：
    - 標記語法可疑、潛在的問題語法或指令
    - 開發過程中減少錯誤的產生
    - 幫助團隊建議易讀性高、維護性好的coding style
    - 減少針對coding style的爭論，有助於code review
    - 提高coding品質

- 特色:
    - 高度設定彈性，可依需求或喜好設定
    - 具有擴充功能，函式庫或框架的開發者，可以依照需求再開發擴充


[What Is a Linter? Here’s a Definition and Quick-Start Guide](https://www.testim.io/blog/what-is-a-linter-heres-a-definition-and-quick-start-guide/)
[ESLint - Lint工具的後起之秀](https://ithelp.ithome.com.tw/articles/10184924)

# binary search

## 簡介

在**有序**陣列中搜尋某一特定元素(target)的演算法，永遠都從中間元素開始：

1. 若該target等於中間元素，搜尋結束
2. 若該target大於中間元素，則搜尋該陣列右半邊區塊
3. 若該target小於中間元素，則搜尋該陣列左半邊區塊

![image alt](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/cd4a973b-9504-4dba-ad6d-7d5c5bfc7849/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210822%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210822T025829Z&X-Amz-Expires=86400&X-Amz-Signature=ab6c73514d2386d9a9900c7b17ee8e1bcc2c0f1cd83729daef6b1039213685dc&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22)
## 時間複雜度：

O(log n)

## 條件：

需要事先被排序

## 實作

[Gist實作](https://gist.github.com/tim80411/10db0011ad90dcae6f988e313ea4f0ae)
![](https://i.imgur.com/fN1Iswx.png)


# Insertion Sort(插入排序法)

## 簡介

將第i元素放入「前i - 1張排序過」的組合，可以得到i張排序過的組合。

意思是說，如果我從第一張重新開始排序，就必定能確保排序N次後能得到長度為N的已排序組合。

2, 3, 4

- [ ]  [4, 2, 3 ]

24

2,4

2,3,4

## 關鍵問題

概念知道了，但核心在於當我要插入第i元素時，要如何知道要插入到1~i-1筆資料中哪個位置呢?

- 透過一個一個比較： for loop 1~i-1，遇到大於自己的index就插入到index - 1減1的位置
- 倒過來比較，避免length增加造成的無線迴圈
- 到達index === 0的地方要判斷是大於還是小於

2,3,4

## 實作

[Gist實作](https://gist.github.com/tim80411/87446e3792e1d954b1b66a4b80ac1855)
![](https://i.imgur.com/axMpBTV.png)


## 時間複雜度

![image alt](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/652a68d7-384b-4b16-8778-0ced3d945d85/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210822%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210822T030138Z&X-Amz-Expires=86400&X-Amz-Signature=aca0c1cccf45c5e7f715629905833bee51c61533f6bdb01f96deee5b47a2a690&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22)

[http://alrightchiu.github.io/SecondRound/comparison-sort-insertion-sortcha-ru-pai-xu-fa.html](http://alrightchiu.github.io/SecondRound/comparison-sort-insertion-sortcha-ru-pai-xu-fa.html)

- best case：越接近完成排序的狀況下，時間複雜度會越接近O(N)
- worst case：如果是完全倒序的狀況下，N-1個元素都需要比較N-1次，時間複雜度是(N-1)平方：O(N$^2$)