---
# System prepended metadata

title: '2022 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2022)」作業 1'
tags: [資訊科技產業專案設計作業]

---

---
tags: 資訊科技產業專案設計作業
---
# 2022 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2022)」作業 1
> 貢獻者: 威爾 will
> [video1](https://www.youtube.com/watch?v=DfnONCAPgGo)、[video2](https://www.youtube.com/watch?v=XJInRbG92No)

🧔：interviewer    👶：interviewee

## [230. Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/)

### 測驗說明與問答
🧔：希望 will 可以實作一個 function，輸入一個二元搜索樹(BST)，這個 function 可以找出裡面第 k 小的元素。
👶：好的您的問題是給我一個二元搜尋樹，然後我要想辦法找出裡面由小到大排在第 k 位的點的值嗎?：
🧔:是的，沒錯!
👶:那首先對這個問題提出一些案例
```
Example 1:
    Input:
        k = 1
        BST:   3
              / \
             1   4
              \
               2
    Output: 1

Example 2:
    Input:
        k = 3
        BST:   5
              / \
             3   6
            / \
           2   4
          /
         1
    Output: 3
```
👶：另外假設至少有一個點。
👶：我剛開始想到的方法是用遞迴解，以 inorder 的方式走訪整顆二元搜尋樹，因為 inorder 會按照二元搜尋樹的點由小到大走，因此我只需要再走的時候順便做 K 值的計算就可以找到答案
🧔：這樣的時間複雜度是如何？
👶：由於需要遞迴的訪問每一個節點執行函數，故時間複雜度為$O(n)$

### Kth Smallest Element in a BST
```c=
struct TreeNode {
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
};

void inorder(struct TreeNode* node, int* k, int* ans) 
{
    if (node) { 
        inorder(node->left, k);
        if (--*k == 0) {*ans = node->val;return;}
        inorder(node->right, k);
    }
}
```

🧔：如果這個 BST 很常被更改(插入/刪除)，且你也很常需要找到第 k 小的元素該怎麼辦？
👶：我的想法是在 ```struct TreeNode``` 中多加一個成員叫做 ```count``` 用來紀錄這個點的左右子樹的點數再加上自己(1)的總節點數，這麼一來每當 BST 在新增或刪除時也更新 ```count``` 的前提下，時間複雜度可以是$O(h)$，```h``` 代表樹高

### Follow up
```c=
struct tTreeNode{
    int val;
    int count;
    struct tTreeNode* left;
    struct tTreeNode* right;
};

void kthSmallest(struct tTreeNode* root, int k, int* ans)
{
    int leftcount = root->left ? root->left->count : 0;
    if (leftcount+1 == k) {*ans = root->val; return;}
    else if (leftcount+1 > k) kthSmallest(root->left, k, ans);
    else kthSmallest(root->right, k - leftcount - 1, ans);
}
```

## [101. Symmetric Tree](https://leetcode.com/problems/symmetric-tree/)

### 測驗說明與問答
🧔：在第二題我給你一個二元樹，請你檢查這棵樹是否為左右對稱(Symmetric)。
👶：沒問題，所以我會有一棵二元樹，然後我要檢查這棵樹是否左右對稱。
🧔：是的，沒錯
👶：好的那麼要處理這個問題，比如說下面這個例子
```
下面這顆是 symmetric tree
    1
   / \
  2   2
 / \ / \
3  4 4  3
```
👶：我一開始想到的方案是利用遞迴的方式來解，比如說看到 root 的左右節點(2, 2)簡稱為左節點跟右節點，這邊可以判斷(1)左節點的左子樹跟右節點的右子樹是否對稱、(2)左節點的右子樹與右節點的左子樹是否對稱，來判斷這顆 BT 是否為對稱樹
👶：另外寫程式時還要注意到子樹是空的的情況
```c=
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

bool isSYM(struct TreeNode* L, struct TreeNode* R)
{
    if (!L && !R) return true;
    else if (!L || !R) return false;
    if (L->val == R->val) {
        return isSYM(L->left, R->right) && isSYM(L->right, R->left);
    }
    else return false;
}

bool isSymmetric(struct TreeNode* root)
{
    return isSYM(root->left, root->right);
}
```
🧔：好的，那麼接下來想請問有沒有非遞迴的方式
👶：我的想法是用兩個 ```queue```分別存 root 的左右子樹的點，把每次走到的點 pop 出去，然後 push 進它的左右子點。來達成iteration 的解法
👶：舉例來說
```
    1          queue1     queue2     判斷兩個queue head 有沒有相同
   / \                               有就把他們pop掉，然後push他們的左右子點進來
  2   2           [2]        [2]     這邊要注意到兩個 queue push 左右子點的順序要對稱    
 / \ / \   
3  N 4  3   [3, NULL]     [3, 4]
```
👶： C 語言因為沒有 queue 結構，所以這邊我要用 linked list 來實作簡單的 queue
```c=
 struct TreeNode {
     int val;
     struct TreeNode *left;
     struct TreeNode *right;
 };

struct qnode{
    struct TreeNode *node;
    struct qnode *next;
};

void insert(struct qnode *tail, struct TreeNode *tnode)
{
    struct qnode *n = malloc(sizeof(struct qnode));
    n->node = tnode;
    n->next = NULL;
    tail->next = n;
}

bool isSymmetric(struct TreeNode* L, struct TreeNode* R) 
{
	struct qnode* L_head = &(struct qnode){struct TreeNode* L, NULL};
	struct qnode* R_head = &(struct qnode){struct TreeNode* R, NULL};
	struct qnode* L_tail = L_head;
	struct qnode* R_tail = R_head;
	while (L_head && R_head) {
		struct TreeNode* L = L_head->tnode;
		struct TreeNode* R = R_head->tnode;
		
		if (!L && !R) {
			L_head = L_head->next;
			R_head = R_head->next;
			continue;
		}
		else if (!L || !R) return false;
		else {
			if (L->val != R->val) return false;
			else {
				insert(L_tail, L->left);
				L_tail = L_tail->next;
				insert(L_tail, L->right);
				L_tail = L_tail->next;
				L_head = L_head->next;
				
				insert(R_tail, R->right);
				R_tail = R_tail->next;
				insert(R_tail, R->left);
				R_tail = R_tail->next;
				R_head = R_head->next;
			}
		}
	}
	return true;
}
```
# info2022-homework2
### [面試檢討 - 他評 01](https://hackmd.io/@sysprog/HJmh9FlGs)
### 優點
* 有重複問題和舉例討論。
* 口齒清楚
### 缺點
* 過場的時候可以用字幕標記 interviewer 和 interviewee
* [2:20](https://www.youtube.com/watch?v=8o5xDyZW-L0#t=2m20s) interviewee 在說想法時可以搭配打字舉例說明會比較好懂
* [2:52](https://www.youtube.com/watch?v=8o5xDyZW-L0#t=2m52s) interviewer 在這邊可以把題目從 32 bits 改成 8 bits 之類的，可以避免冗長的打程式過程
* [3:20](https://www.youtube.com/watch?v=-MmBAeRkeDc#3m20s) interviewee 可以先問能不能用標準函式庫
### [面試檢討 - 他評 02](https://hackmd.io/@sysprog/SyxXzTYgGi)
* 優點
    * 口試清楚，對答流暢
* 缺點
    * [0:10](https://www.youtube.com/watch?v=eG_ckTWiW8s#0m10s) 記得不要講面試官
    * [0:29](https://www.youtube.com/watch?v=eG_ckTWiW8s#0m29s) interviewer 在說明題目時可以打一些範例來讓 interviewee 更能理解題目
    * [0:56](https://www.youtube.com/watch?v=eG_ckTWiW8s#0m56s) interviewee 跳過 repeat，直接進到 approach 的部分了
    * [9:28](https://www.youtube.com/watch?v=eG_ckTWiW8s#9m28s) 寫完可以先問問看 interviewer 的意見，之後再試著最佳化，比較有互動感
### [面試檢討 - 他評 03](https://hackmd.io/Jg0pMfMtSDmUeNjvhOT7wA?both)
* 優點
    * interviewee 有停頓下來思考，不會讓人誤以為是背答案
    * 口齒清楚
* 缺點
    * [0:02](https://www.youtube.com/watch?v=Wy88DIP9j1o#0m02s) 記得不要講面試官
    * [0:11](https://www.youtube.com/watch?v=Wy88DIP9j1o#0m11s) interviewer 說明題目時可以搭配打字讓 interviewee 更好理解
    * [3:54](https://www.youtube.com/watch?v=Wy88DIP9j1o#3m54s) interviewer 提問時不應說能快點嗎，可以提出一個時間複雜度給 interviewee 思考
### [面試檢討 - 他評 04](https://hackmd.io/@sysprog/BJ_179gfo)
* 優點
    * Interviewer 說明簡單明瞭，也有用圖來表達範例，讓 interviewee 更好理解
    * Interviewee 有先向 interviewer 確認對題目的理解，然後再提出自己的想法
    * Interviewee 口齒清楚，表達也很流暢
    * Interviewee 有做到在撰寫程式碼的同時講出自己的想法
* 缺點
    * Interviewer 可以向 interviewee 討論複雜度，然後再討論有沒有其他的 approach
    * [2:12](https://www.youtube.com/watch?v=a8EAkMWPkB8#t=2m12s) 不是叫空子樹，要叫做這棵樹為空(空集合)
### [面試檢討 - 他評 05](https://hackmd.io/EIw2WNFWQ2OI0cVfJqRGmA?view)
* 優點
    * Interviewer 的說明簡單明瞭，也有用圖來表達範例，讓 interviewee 更好理解
    * Interviewer 可以向 interviewee 討論複雜度，然後再討論有沒有其他的 approach
    * Interviewee 有先向 interviewer 確認對題目的理解，然後再提出自己的想法
    * Interviewee 有做到在撰寫程式碼的同時講出自己的想法
* 缺點
    * [5:16](https://www.youtube.com/watch?v=2614P2z1bg8#t=5m16s) Interviewee，Auto-Complete 記得要關掉
    * [9:37](https://www.youtube.com/watch?v=2614P2z1bg8#t=9m37s) Interviewee 可以用快慢指標來最佳化
    * Interviewee 打字時盡量不要轉頭