---
# System prepended metadata

title: 8/6讀書會(電腦科學、開發工具)
tags: [面試考古題]

---

# 8/6讀書會(電腦科學、開發工具)
###### tags: `面試考古題`


==翊廷==
https://www.notion.so/8-6-5ce21f43917c416a9349ad96724e3340
# Tree(資料結構)

## 什麼是Tree?

用來描述具有階層結構問題的首選，階層代表順序。

只有一個root，且不存在cycle→

1. 節點只存在一條路徑
2. 每個節點只有一個parent

常見的元素/定義

1. **degree(分歧度)**：一個node擁有的subtree(子樹)的個數。
    - 圖四，A的degree為3，F的degree為2，N的degree為0。
2. **root(樹根)**：樹中最上層的node，也是唯一一個其parent為**NULL**的node。
    - 圖四，A即為root。
3. **leaf**：沒有child/subtree的node稱為leaf node。
    - 圖四，G、H、J、K、L、M、N皆為leaf node。
4. **external node**：沒有child的node。因此，leaf node與external node同義。
5. **internal node**：至少有一個child的node，稱為internal node。
    - 圖四，A、B、C、D、E、F、I皆為internal node。

## 可以用來做什麼?

方便快速找資料

## 常見概念

時間複雜度、空間複雜度

EX：DOM Tree 搜尋的時間複雜度是什麼?

## 樹的變化：

1. 二元樹→二元搜尋樹

## 二元搜尋樹：

1. 比此node小的會在節點左邊，反之右邊
2. 每個node只有兩個child
3. BFS 廣度優先搜尋 v.s. DFS 深度優先查詢

## 舉例

目錄、族譜、企業職位關係、心智圖、DOM tree

## 參考資料

[Tree(樹): Intro(簡介)](http://alrightchiu.github.io/SecondRound/treeshu-introjian-jie.html)

[[資料結構] 樹 Tree](https://medium.com/starbugs/%E8%B3%87%E6%96%99%E7%B5%90%E6%A7%8B-%E6%A8%B9-tree-1cfddf5685ce)



# Git Flow

## 什麼是Git Flow

是有人提出的一套流程讓大家共同遵守，有五種branch定義及功能，分別是master、develop、hotfix、release 以及 feature。

1. develop及master會一直存活在Git flow中。
2. 其餘支援性(Supporting)branch會因為任務結束建議刪除。

## Branch功能介紹：
![image alt](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d90d1dd6-ab12-4d94-83af-a1122faf8626/Untitled.png)

- Master
放置穩定、可隨時上線的版本，不會直接commit到這個branch，而是合併其他branch而來，常會使用版本號標籤。
- Develop
由master一開始分支而來，是所有開發分支的base，所有feature都從這邊分支出去，也會在開發完成後合併進來。
- Hotfix
master的穩定產品出現重大緊急問題時，會開hotfix做修復，修復完成後會合併回master，也會合併進develop，避免後續develop合併回master時出現一樣問題。
- Release：不應該有新功能
若是Develop成熟後會開release分支，此分支不應該有新功能，僅測試bug，是上線前的最後測試，OK後會合併回master，如果過程有針對bug做額外修正時需要merge 回develop做更新的概念。
- Feature：只會被merge回develop分支
若有新功能需要開發就是從Develop開分支出來，也可以依據需求從其他feature分支分出來。
開分支時建議前綴 `feature + / + 功能名` 例如： `feature/filter`

## 狀況題

### 遠端的 feature 分支有新的 commit

可以使用`git pull --rebase origin feature/myFeature`

邏輯概念參考[大大](https://blog.hellojcc.tw/understanding-git-flow/)：把目標分支可以fast forword的commit都merge到目前分支(此案例應該是在`feature/myFeature`)，再把目前分支有的commit一個一個加/插入(?)回去。

因為是同個功能開發，理所當然遇到conflict機率高，但rebase好處是可以看到每個commit遇到conflict的地方，merge的話會是一次處理所有commit的conflict。

## 補充：對於git flow修正的建議與討論

### develop的存在必要性?

- *hotfix*: 已經出版的舊有功能需要修正
- *feature*: 要新增新的功能
- *release*: 由feature分支而來，集結下一個版本要的功能，在這裡修正 bug 後準備出版，進到 *master*

### 問題：

- 不必要的相依性：F1、F2

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/986c6cd8-a54e-4a69-9fd7-66a382dcd2fa/Untitled.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/986c6cd8-a54e-4a69-9fd7-66a382dcd2fa/Untitled.png)

- 重複的流程

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/974c06ef-bf2f-41d1-9be8-7a20eadf680b/Untitled.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/974c06ef-bf2f-41d1-9be8-7a20eadf680b/Untitled.png)

暫時解答：[看開發的CI環境的設定](https://blog.wu-boy.com/2017/12/github-flow-vs-git-flow/)，

## 參考資料：

[Git Flow 是什麼？為什麼需要這種東西？ - 為你自己學 Git | 高見龍](https://gitbook.tw/chapters/gitflow/why-need-git-flow.html)

[git flow 實戰經驗談 part1 - 別再讓 gitflow 拖累團隊的開發速度](https://blog.hellojcc.tw/the-flaw-of-git-flow/)

[A successful Git branching model](https://nvie.com/posts/a-successful-git-branching-model/)

[了解 Git Flow](https://blog.hellojcc.tw/understanding-git-flow/)

# 敏感資料的儲存

## 問題：

在 Rails 專案中，config/database.yml 這個檔案裡有資料庫的設定、帳號密碼等資訊，在使用 Git 時，你通常會怎麼處理這類型內容比較敏感的檔案？

## 另外給定.env檔案切換不同環境所需變數(使用dot.env等套件)

### 方式：

在development時去讀取.env檔，並且同時在.gitignore上設定忽略，避免將這些資料被公開。

### 優點：

方便又簡單!!!!!!

### 缺點：

1. 若有設定必須修改就要重新上新版本
2. 難保沒有人為失誤不小心將機密資料上git

## kubernetes管理

### 方式：

使用他提供的config map及secrets解決

## AWS Paremeter Store @ AWS System Manager

### 方式：

# merge vs rebase @ 大量conflict

## 問題

兩個 branch 各有五十個 commit 要接起來時，極有可能會出現大量的 conflict ，這時你會選擇用 merge 還是 rebase 處理它？哪個可能比較方便（或比較少的衝突）？為什麼？

## 簡單解答

merge會一次性解決所有conflict，比較容易；而rebase會多次解決，並針對不同次commit造成的衝突進行更改。

merge是把要merge的最後一個commit做合併；rebase則是一個個commit合併進去，所以可能會有多次的衝突須要解決

## rebase細節

可以一次處理多個commit，概念就如同高見龍說的，re-base，重新變換基礎。

![https://www.maxlist.xyz/wp-content/uploads/2020/05/git_rebase.gif](https://www.maxlist.xyz/wp-content/uploads/2020/05/git_rebase.gif)

### 流程

1. `git rebase <commit_id> [-i | --interactive]`會在VI介面產生一個rebase todo list，並逐項執行rebase todo
2. `git rebase --continue`每次改動好就使用此指令繼續下一項rebase todo

### 額外指令

1. `git rebase --skip`跳過當前rebase todo
2. `git rebase --abort`跳出整個rebase

## 參考資料

易懂：多圖

[多圖rebase講解](https://www.maxlist.xyz/2020/05/02/git-merge-rebase/)

中：機制的比較

[Git: 更新分支+解衝突 | Summer。桑莫。夏天](https://cythilya.github.io/2018/05/27/git-merge-and-solve-conflict/)

[機制比較](https://kknews.cc/zh-tw/news/k8alv2v.html)

複雜：Git較底層知識、原理，但有圖片、實作

[Rebase 與 merge conflict 機制](https://medium.com/@RiemannAC/rebase-%E8%88%87-merge-conflict-%E6%A9%9F%E5%88%B6-b01f0d49d747)

==TINA==
## Linked List
### 1. 重點

- 與陣列一樣都是**線性資料結構**，但不同於陣列，它為鏈式儲存結構，也就是記憶體位置儲存為不連續性。
- 等於是自己創造一個資料結構
- 使用Linked List可以克服陣列串列需要預先知道資料大小的缺點，Linked List可以充分利用電腦記憶體空間，實現靈活的記憶體動態管理。但是失去了陣列隨機讀取的優點，同時Linked List 由於增加了結點的指標域，空間開銷比較大。

### 2. 定義

Linked List 是由一連串 **節點（node）** 組成，節點之間是透過 pointer 來連接。所以儲存上並不需要連續的空間。

每個節點包含：

- 資料元素
- pointer 若沒有上／下一個節點，則為 Null。如果pointer斷裂，資料就遺失在記憶體大海中。

舉生活上的例子來說，鏈結串列如同火車的車廂一樣，一節拉著一節。

因為Linked List沒有index，若要存取特定node，需要從頭開始找起，因此相較於陣列，存取資料較費時。

### 2. 類型

鏈結串列有很多種不同的類型：

- 單向鏈結串列（Singly Linked List）
- 雙向鏈結串列（Doubly Linked List）
- 迴圈鏈結串列（Circularly Linked List）

### 單向Linked List

是最基本的鏈結串列，其特點是鏈結串列的鏈結方向是單向的，對鏈結串列的存取要通過從頭部開始，依序往下讀取。

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

[讀書會時的簡報檔案](https://drive.google.com/file/d/1I6WMkZyS2F-j2AtfSqNdESyjBIwbiSDA/view?usp=sharing)

[中文教學](https://chupai.github.io/posts/200427_ds_linkedlist/)

[英文教學](https://www.freecodecamp.org/news/implementing-a-linked-list-in-javascript/)

### LEETCODE 可研究題目
[https://leetcode.com/problems/palindrome-linked-list/](https://leetcode.com/problems/palindrome-linked-list/)

[https://leetcode.com/problems/remove-linked-list-elements/](https://leetcode.com/problems/remove-linked-list-elements/)

## 版本管理系統是什麼？為什麼要用
### 1. 定義
「版本控制系統」，就是指會幫你記錄這些所有程式碼的狀態變化，並且可以隨時切換到過去某個「版本」時候的狀態。

### 2. 解決了什麼問題？
主要使用版本控制系統原因就在備份及協作，不論是個人或是多人協作，都有需要切換到過去某個版本或是還原某個版本的需求，或是共同編輯專案的需求，但只要協作的人一多，備份檔案就會更多，也有可能程式碼被別人或自己不小心覆蓋或遺失的問題。

因此更需要版本控制系統來解決這個問題，可以更清楚的記錄每個檔案是誰在什麼時候加進來、什麼時候被誰修改或刪除

### 補充：
Git 與其他版控系統最大的差異就於，他是「分散式儲存」， DVCs（Distributed Version Control System） 將資料分散於不同設備上(就是儲存資料的本地端)，如此一來，就算其中一處設備損壞，也不影響其他用戶使用。

集中式版本控制：
這類系統（如：CVS、Subversion 和 Perforce），都有一個伺服器來管理所有版本的檔案，而許多用戶端會連到這台伺服器取出檔案來使用。
* 優點
    每個人都可以一定程度的知道專案中的其他人正在做些什麼。 
    管理員也可以輕鬆掌控每個開發者的權限。 
* 缺點
   最嚴重的當然是中央伺服器如果發生故障的時候。 如果當機一小時，那麼這個小時之中，沒有人可以提交更新，也就無法協同合作。 
   如果中心版本庫的硬碟發生損壞，又沒有做適當的備份，那麼你就絕對會遺失所有資料——包括專案的全部變更歷史，只會剩下用戶端各自機器上保留的單獨快照。

參考資料：https://git-scm.com/book/zh-tw/v2/%E9%96%8B%E5%A7%8B-%E9%97%9C%E6%96%BC%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6

## 請寫下從 Github 上複製一個專案下來，做一次遞交，然後推上去會用到的所有 git 指令。

1. 從他人 gitHub 專案 fork 到自己的 repository
2. clone 自己的 repository，在本地的 Terminal 輸入`git clone 請求網址`
（Clone 指令會把整個專案的內容複製一份到你的電腦裡，這裡指的「內容」不是只有檔案，而是指所有整個專案的歷史紀錄、分支、標籤等內容都會複製一份下來。）
3. 再修改程式碼後透過 `git add .` 登記檔案變動
4. 透過 `git commit -m "WRITE SOMETHING"`  建立版本細節
5.  `git push origin <分支名稱>`
6. 到原先專案的擁有者 gitHub 頁面 pull request 合併回原專案

[參考連結](https://ithelp.ithome.com.tw/articles/10140305)

## 當多人協作時你要開發個功能，但不影響主程式，該怎麼作呢？要下什麼指令？開發好功能後需要下什麼指令合併回主程式？如果衝突了要如何處理？

假設團隊已開立 Develop 分支 + 使用 git flow + 已經處理過上一題的流程 

1. **`git checkout develop`**
2. 從 Develop 再開一個 Feature branch：**`git checkout -b Feature-branch`** 後就可以開始在這個分支上修改程式碼
3. 完成編輯後，再回到 Develop 分支：**`git checkout develop`**
4. 先取得最新的 Develop 分支狀態： **`git pull 原專案Develop`**
5. 若有衝突，可以回到程式碼區塊查看衝突發生的點，並且與團隊討論
6. 修改完衝突後 **`git add 衝突發生檔案`** 把這個檔案登記檔案變動
7. 說明衝突情況 **`git commit -m "WRITE SOMETHING"`**
8. 合併 Feature branch 到 本地Develop 分支：**`git merge Feature-branch`**
9. **`git pull`**  自己的遠端 develop分支
10. 到原專案擁有者的頁面 pull request


==YJ==

## Graphs（資料結構）
### 圖是什麼？
  - 柯尼斯堡七橋問題（The Königsberg Bridge Problem）
    - 東普魯士柯尼斯堡（今俄羅斯加里寧格勒）市區跨普列戈利亞河兩岸，河中心有兩個小島。小島與河的兩岸有七條橋連接。有人就開始想，在所有橋都只能走一遍的前提下，如何才能把這個地方所有的橋都走遍？
    ![七橋問題](https://i.imgur.com/ArTlXPR.png)
    - 尤拉把問題的實質歸於一筆畫問題，即判斷一個圖是否能夠遍歷完所有的邊而沒有重複。對於一個給定的連通圖，如果存在超過兩個（不包括兩個）奇頂點，那麼滿足要求的路線便不存在了，且有 n 個奇頂點的圖至少需要 n/2 筆畫出。如果只有兩個奇頂點，則可從其中任何一地出發完成一筆畫。若所有點均為偶頂點，則從任何一點出發，所求的路線都能實現。
  - 定義：圖 (Graph)，在資料結構上指的是點和點之間的關聯的東西，並不是數學定義上的兩點成一線，三點成一面的那種圖。一張圖由數條邊 (Edge) 和數個點 (Vertex) 所構成，點和點之間可用邊相連，表示這兩個點之間有所關聯。兩點之間可以有多個邊，一個點可與多個點相連。



  - 有向圖 vs 無向圖
  ![](https://i.imgur.com/CahKz5G.png)
    - 有向圖：G = (V, E), 其中V為頂點集合，E為邊集合。邊集合中的毎一個邊都有方向性，以指向下一個頂點。
    - 無向圖：G = (V, E), 其中V為頂點集合，E為邊集合。 邊集合中的毎一個邊都沒有方向性。

  - 若要表示一個圖形，需要儲存兩個集合：頂點 & 邊


### 圖常用的儲存方式：

   - Adjacency matrix 相鄰矩陣：把一張圖上的點依序標示編號，然後建立一個矩陣，來記錄連接資訊。方陣中的每一個元素都代表著某兩點的連接資訊。
  ![](https://i.imgur.com/6C07Peo.png)
  - Adjacency list 相鄰串列：在每一個點後方，串連所有相鄰有連接的點
  ![](https://i.imgur.com/2mYUVBG.png)


### 圖的遍歷 Traverse Graph（檢查 Graph 是否連通？）
  - Depth First Search (DFS；深度優先搜尋)
  ![](https://i.imgur.com/GKZFSxp.gif)
  - Breadth First Search (BFS；廣度優先搜尋)
  ![](https://i.imgur.com/kzZTa91.gif)



## Rebase
![](https://i.imgur.com/9zBfBHi.png)
  - Rebase -> Re + base -> 重新定義分支的參考基準
  - 用途：將所有歷史 commits 放在同一條線上，若用 merge 會留下 merge commit，如果 merge 很多次線圖會有很多 merge commit，很醜而且回看的時候會很亂不乾淨。但若用 rebase 是直接把 commits 拉到別的基準，不會生成新的 commit 紀錄，線圖就會很美（但同時也代表分支紀錄會消失，會找不到這個功能的上源是什麼）。
  - Interactive Rebasing
    - 用途：ex: develop merge 回 master 前清理線圖用
    ```
    git checkout feature
    git rebase -i master
    ```
    - 在 terminal 打上面的指令後會出現如下圖的畫面
    ![](https://i.imgur.com/G7PORny.png)

    - 可以依據 git 的指令提示更改自己的 commit 紀錄
    ![](https://i.imgur.com/xT8pAWt.png)

    - 例如像上圖把 `pick` 改成 `fixup` 後就會把第一個 commit 跟第二個 commit 合成同一個 commit
    ![](https://i.imgur.com/Z5qvDH3.png)


### Rebase 準則：
==不能用在別人在用的分支上（ex: master 或任何推上 remote 的）==


## 為什麼 Git 稱作「分散式」版本管理系統？
- 版本管理系統：
  - Local version control 本地式：都在自己本機
  - Centralized version control 集中式：都在系統上
  - Distributed version control 分散式：有存在本機的但也可以推上去讓其他人取得
- 定義：軟體開發者可以共同參與一個軟體開發專案，但是不必在相同的網路系統下工作。每個開發者電腦中複製一份完整的 code 以及完整歷史，因此在無法連接網路時，仍可以進行軟體的分支及合併，可以加速大部份的作業，而且可以在多家電腦上備份，不需靠單一位置的備份。不同位置的資料再透過其他機制來達到同步（push, pull）。
- 分散式管理系統優點：
  - 使用者在沒有網路的情形下，也可以存取其電腦中的軟體儲存庫。
  - 常見工作（例如上傳、看修改履歷、回退變更）不需要和中央伺服器通訊即可達成，只有要和其他人分享變更內容時才需要通訊。
  - 允許個人作業，使用者可以將不希望公開的早期修改（甚至是草稿）上傳
  - 工作複本的作用類似遠端備份，因此不會依賴單一的實體機器，分散風險


## 什麼是 staging area？（暫存準備遞交區）
![](https://i.imgur.com/vfF6UdJ.png)

- Staging area 在提交 commit 出去後並不是空的，而是儲存著最後那次的 commit，這樣對檔案有變動的時候，因為新的變動跟本來儲著的最後 commit 有差異，就可以知道有更改
- 優點：
  - Working tree 可能很亂，包含了想要 commit 的內容和不相關的實驗修改等，Staging area 的設計可以讓你只 commit 想要的檔案，甚至是想要的部份修改而已


==Marco==

## HashTable 雜湊表 (哈希表)
- 定義：由key-value組成的pair
- 類似於arrray存資料的方式，差別在於，array是用位置儲存，但hash table是根據key而直接查詢在記憶體儲存位置
- 可以用`Map`、`Object`做為hash table使用 (也可以用array製作，用index當key)

- 優點：
    - 資料量大時，相較於array的靠位置找資料，直接用key來找資料的速度較快

將key透過hash function對應到特定的記憶體位置就是hash table，若使用object, Map的話JavaScript會自行幫我們做hash function

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


[Leetcode 136. Single Number](https://leetcode.com/problems/single-number/)
[Repl](https://replit.com/@MarcoLin1/test-2)

### HashTable collision怎麼辦？
1. 一個一個往下移
2. linked list


### Map
- 類似object的key-value pair

```javascript=
let map = new Map([
    ['one', '123']
])

map.set('two', '456') //修改
map.get('two')       // 取得資料
map.delete('two')    // 刪除
```

### Map與Object有何不同
Object: 沒有順序，key的格式都是String
Map: 有時間順序 (依照加入的時間排序，first in first out)，key的格式可以是任何格式


## GitHub Flow
- 定義：工作流程的一種，以主分支`master`為基底，不論是解issue或者開發新功能，都是從主分支再開其他分支，讓主分支時常保可以部署的狀態
- 流程：
    1. 建立團隊的repo
    2. 團隊成員fork團隊的repo到自己帳號
    3. 開新的feature
    4. 增加commit (修改後)，將feature推到GitHub上
    5. 針對團隊的repo發PR
    6. 討論並檢核code
    7. merge回主分支，部署到production環境 (也有可能先部署到測試環境)


[GitHub Flow](https://guides.github.com/introduction/flow/)
[三種版控流程](https://medium.com/@lf2lf2111/%E4%B8%89%E7%A8%AE%E7%89%88%E6%8E%A7%E6%B5%81%E7%A8%8B-29c82f5d4469)

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


## GitLab Flow
- 定義：
    - 只有一個主要分支，所有的分支都是從主分支建立
- 原則：
    - upstream first (上游優先)，只存在一個主分支master，是所有其他分支的上游，只有上游採納的程式碼變化後，才能應用到其他分支，除非是緊急情況，才允許跳過上游直接在下游操作合併
- 工作流程： (持續發布的專案)
    - 有三個分支，分別為master (開發環境)、pre-production (預發環境)、production (生產環境)
    - 如果production發生問題，先建立一個分支修改完後合併到master
    - 經過測試沒問題後再合併到pre-production
    - 在pre-production測試沒問題後，再合併到production

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


## 空的資料夾無法被加入 Git 進行版本控制，但這個資料夾如果又是很重要的資料夾，你會怎麼處理？

- 原因：
    - Git在計算、產生物件的時候，根據『檔案的內容』做計算的，所以空的資料夾沒有檔案內容，Git無法處理

- 解決方法：
    - 在空目錄裡隨便放一個檔案就行了 <font color="red">(大家的想法和高見龍大大一樣，英雄所見略同！！！)</font>
    - 慣例上會放一個名為『.keep』、『.gitkeep』的空檔案



