貢獻者: 起司堡-cheeseburger
🎩:interviewer 🍔:interviewee
[影片 (漢語)]
Question Description
🎩: Given an integer array nums
,if any value appears at least twice in the array return true
, if every element is distinct return false
Repeat and Examples
🍔: 是否可以改寫或調動 input array 的內容?
🎩: 可以
🍔: 是否只要當重複 value 出現時,便可以直接輸出 True/False?
🎩: 是
🍔: 依照您所給的 Constraints,所以我不必考慮 nums = []
或是若我以 C 語言實作並指定 pointer to int 來接收 input array,我暫時不必考慮被傳入 NULL
pointer?
🎩: 不會被傳入空陣列或 NULL
pointer,假設都傳入合法整數陣列
#Approach
🍔: 我想這個題目可以使用 Hashtable 來處理,(說明演算法同時註解,請參照影片),不過由於 C 語言的 Standard header 並沒有提供 Hashtabled 的實作,為了方便演算法的實作與解說,我希望可以使用 uthash 這個第三方開發的 header file 裡的 macro 來輔助解題。就我所知,uthash 已經被 include 於目前的 LeetCode,並且 uthash 的官方文件中強調它大部分程式碼以 macro 撰寫,其 Add, find, delete 操作通常都能在常數時間完成。
Is uthash fast?
Add, find and delete are normally constant-time operations. This is influenced by your key domain and the hash function.This hash aims to be minimalistic and efficient. It’s around 1000 lines of C. It inlines automatically because it’s implemented as macros. It’s fast as long as the hash function is suited to your keys.
🎩: 可以,用吧 (yes I know that, and you can use uthash header if that help you expain your implementation.)
Code
Test
🎩: 好,那麼分析一下時間複雜度吧
🍔: O(n),improvement 策略:不需要 counts (假設一開始定義 element_t 時不小心定義 count 變數的話)
可能的 Follow-up
🎩: 你剛剛說你有看過 uthash 的官方文件,可以大致說明一下 uthash 的實作方式嗎?
🍔: uthash.h 和 linux kernel 所提供的 hashtable.h 的實作方式有些微不同,兩者都是建立一條單向鏈結串列作為 buckets,透過 uthash 提供的 hash function 可以將 key 對應至其中一個 bucket,接著每個 bucket 會有一個 head 指標指向一條雙向鏈結串列,每個 node 允許使用者封裝成自訂義物件,也就是我剛才所定義的 element_t。
我認為 uthash.h 為了增加 hashtable 的使用方便性,其實作相對 linux kernel 的 hashtable.h 複雜許多,uthash.h 提供的 UT_hash_handle 其實是多種指標、變數的複合結構體,bucket 和 element_t 的結構都要嵌入 UT_hash_handle,但不是每個變數或指標都會用上,若想要去更改 HASHTABLE 的實作細節,反而讓開發變得困難。而 linux kernel 提供的 hash table 相關實作比較像是各種小模組、小零件,結構設計上有專業分工,例如雙向鏈結串列的 hlist_node 只用於 element_t、單向鏈結串列的 hlist_head 只用於 buckets 指向各自的 hlist_node,對程式開發者而言,自由度更高。
面試過程
void *prev, *next;
而 bucket order 是 struct UT_hash_handle hh_prev, hh_next
:
程式部分
同儕互評
Interviewer
Interviewee
Interviewee
Interviewer
整體檢討:因為使用c語言實作,所以感覺花了很多時間在實作function,整體上比較像是呈現面試者對於c語言下hash table如何實作,所以我看完會有點遺忘問題本身是什麼。
num[i]
範圍只有到 1000 之類的,詢問是否有更好的作法而不用 hash table,或是有沒有除了 hash table 以外的作法[影片 (漢語)] [影片 (英語)]
Question Description
🎩: 這個表格說明合法的 UTF-8 編碼規則,一個 UTF-8 字元可以表示成 1 至 4 bytes 的長度,基本上就是兩大規則。當 UTF-8 字元表示成 1 byte 長度時,第一個 bit 會是零;當 UTF-8 字元表示成 2 bytes 以上 (含) 長度時,會有 n 個 bits 的 1 及 n+1 bits 是 0,n 指的是長度為 n 個 bytes (n > 1)。所以你會有第一個整數陣列型態的 input (複製貼上到 google doc),當然第二個參數是陣列的長度。
Examples
🎩: 你會注意到 example 1 是符合規則的,因為前 2 個 bits 全是 1,第 3 個 bit 為 0 表示它是一個 2 bytes 字元。下一個 byte 是一個以 10 開頭的連續字節,這是正確的。第三個整數是 0 bit 開頭,表示是 1 byte 字元,也符合規則,故回傳 true。
它是 2 bytes 的字元跟 1 byte 字元組成的合法 utf-8 編碼,因為第一個整數轉二進制表示法開頭是 110,表示要看第二條規則;而第三個整數轉二進制開頭是 0,表示要看第一條規則。
而 example 2 是不合法的 utf-8 編碼,因為前 3 個 bits 全是 1,第 4 個 bit 為 0 表示它是一個 3 bytes 字元。
下一個 byte 是一個以 10 開頭的連續字節,這是正確的。
但是第二個連續字元不是以 10 開頭,所以是無效的。
請問到目前有理解嗎?
Repeat and Examples
🍔: 所以我可以當作每一組 input data 是一條資料串流或文字檔案,然後我要循序解碼,第一個整數轉 binary 後,要看前面幾個 most significant bits 來判斷它要接續幾個整數…
🎩: 不是依 most significant bits 判斷,抱歉,這是一個剛剛沒提醒到的 caveat,只有每個整數的最後 8 bits 用於存儲資料,也就是 least significant 8 bits,換句話說每個整數僅代表 1 bytes 的資料。
LeetCode Description:
Note: The input is an array of integers. Only the least significant 8 bits of each integer is used to store the data. This means each integer represents only 1 byte of data.
🍔: 喔! 我懂了,所以整數轉成二進制之後只需要看最後 8 個 bits,再檢查倒數 0 到 5 個 bits,來判斷編碼字元長度,而接續的整數只要檢查轉換後相同規則下是否為 10 開頭即可。而第一個整數只要是 0 開頭就符合。
🎩: 是的,另外這是輸入資料的限制,輸入資料正整數,且至少包含一個數字。
🎩: 所以你要做的事情就是寫個 function,可以讀取一條正整數陣列,並判斷是否符合 utf-8 編碼規則。
Approach
Code
#Test
🍔: time complexity O(n),
🍔: improve from bitmask to bit shifting, == 可以用 !(^) 取代
面試過程
程式部分
可嘗試改進部分
code