# 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\> |