---
# System prepended metadata

title: xarefit 第一階段問卷測驗

---

# xarefit 第一階段問卷測驗
求職者：杜蕙伶
應徵職位：後端工程師 Backend Engineer
語言：python

## 1. 如何寫一個循環，然後把它轉換成遞迴函數？
以印出 0 ~ 2 為例：

- 循環的寫法

```
n = 0

while(n < 3):
    print(n)
    n += 1
```

- 遞迴的寫法
```
n = 0


def count_to_two(n):
    if n >= 3:
        return

    print(n)
    return count_to_two(n + 1)


count_to_two(n)
```

## 2. 如何找出 slow query？ MySQL 如何進行效能分析？
可以在 MySQL 設定 slow_query 相關的參數，紀錄 slow_query 的 log，然後搭配一些效能檢測工具，對 log 做進一步分析

## 3. 索引的優缺點?
優點：
- 加快查詢速度（SQL 查詢語句需要符合某些條件，才會用索引進行查詢）

缺點：
- 需用額外空間儲存索引
- 資料有修改時，索引也需要一並更新，較花時間

## 4. 什麼是 Deadlock？  (用程式碼表示)。
比較粗略地說，Deadlock 是指所有程序都在等別的程序釋放資源給他，導致所有程序都無法執行完畢。


process_A 和 process_B，都需要同時擁有 source_A 和 source_B 才能完成工作。但兩個 process 目前各自擁有一個 source 並且不肯釋出，導致兩個 process 都沒辦法完成工作，變成無限迴圈
```
source_A = {'is_asscessable': False, 'occupier': 'process_A'}
source_B = {'is_asscessable': False, 'occupier': 'process_B'}

is_process_A_done = False
is_process_B_done = False


def process_A():
    global source_A
    global source_B
    global is_process_A_done
    if source_A['is_asscessable']:
        source_A['is_asscessable'] = False
    elif source_A['occupier'] != process_A.__name__:
        return

    if source_B['is_asscessable']:
        source_B['is_asscessable'] = False
    elif source_B['occupier'] != process_A.__name__:
        return

    # do something
    is_process_A_done = True
    source_A['is_asscessable'] = True
    source_B['is_asscessable'] = True
    source_A['occupier'] = ''
    source_B['occupier'] = ''
    return


def process_B():
    global source_A
    global source_B
    global is_process_B_done
    if source_A['is_asscessable']:
        source_A['is_asscessable'] = False
    elif source_A['occupier'] != process_B.__name__:
        return

    if source_B['is_asscessable']:
        source_B['is_asscessable'] = False
    elif source_B['occupier'] != process_B.__name__:
        return

    # do something
    is_process_B_done = True
    source_A['is_asscessable'] = True
    source_B['is_asscessable'] = True
    source_A['occupier'] = ''
    source_B['occupier'] = ''
    return


while(not is_process_A_done and not is_process_B_done):
    process_A()
    process_B()
```


## 5. 寫一段有 memory leak 的示例程式  (用程式碼表示)。
發生 circular reference 的時候，garbage collection 沒辦法收回記憶體
```
a = {'0': 'memory leak'}
b = {'1': a}
a['0'] = b

del a
del b
```

## 6. 查詢列表中的第一個非重複整數 (用程式表示)
> 列表：[3, 6, 6, 3, 2, 1]

```
from typing import Union
from collections import OrderedDict

nums = [3, 6, 6, 3, 2, 1]


def find_first_single_number(nums: list) -> Union[int, None]:
    counter = OrderedDict()
    
    for i in range(len(nums)):
        num = nums[i]
        
        if counter.get(num) is None:
            counter[num] = True
        else:
            del counter[num]

    for i in counter.keys():
        return i

    return None


print(find_first_single_number(nums))  # 結果：2
```

## 7. string = "hgijjigihdgjggeddeihjdji"，如何將字串去重複並排序？並顯示結果
```
string = "hgijjigihdgjggeddeihjdji"


def sort_and_deduplicate(string: str) -> str:
    result = ['' for i in range(26)]
    diff = ord('a')

    for i in range(len(string)):
        index = ord(string[i]) - diff
        
        if result[index] == '':
            result[index] = string[i]

    return ''.join(result)


print(sort_and_deduplicate(string))  # 結果：deghij
```

## 8. 麻煩寫一段程式將[1,4,7,9] 和 [2,3,6,8] 合併為 [1,2,3,4,6,7,8,9]
觀察：給定的兩個 list 已經各自遞增排序完畢了
```
list1 = [1, 4, 7, 9]
list2 = [2, 3, 6, 8]


def merge_list(list1: list, list2: list) -> list:
    result = []
    
    for i in range(len(list1) + len(list2)):
        if len(list1) == 0:
            result.extend(list2)
            break

        if len(list2) == 0:
            result.extend(list1)
            break

        if list1[0] < list2[0]:
            result.append(list1.pop(0))
        else:
            result.append(list2.pop(0))

    return result


print(merge_list(list1, list2))  # 結果：[1, 2, 3, 4, 6, 7, 8, 9]
```

## 9. 寫一個簡單的垃圾回收系統。
構想：計算記憶體被 reference 的次數，次數為 0 的時候就釋放記憶體。

補充：在 JSDC.tw 2021 年會，「Memory Leak 與你的距離」的講者Kuan，有介紹 javascript 的垃圾回收系統，還有做 young generation、old generation 的清除機制

## 10. 如何設計 REST API ？
以部落格貼文 post 此資源為例：

| 操作        | 方法   | 路由                 |
| ---------- | ------ | ------------------- |
| 瀏覽所有貼文 | GET    | posts               |
| 瀏覽一篇貼文 | GET    | posts/\<string:id\> |
| 發表一篇貼文 | POST   | posts               |
| 更新一篇貼文 | PUT    | posts/\<string:id\> |
| 刪除一篇貼文 | DELETE | posts/\<string:id\> |











