# Intro. to Algorithm HW1 ###### tags: `Intro. to Algorithm` - [name=曾文鼎 0716023] ## 1 ### a * 存在 $c=1, n_0=716023, h(n)=n^2$ 使得 $\forall n\geq n_0, 0\leq f(n)\leq ch(n)$ 。 故 $f(n)=O(h(n))=O\left(n^2\right)$ 。 ### b * 以下證明 $\displaystyle\lim_{x\to\infty} \dfrac {g(x)}{\sqrt x}=0$ 。 $$ \begin{align}\lim_{x\to\infty} \frac {g(x)}{\sqrt x} &= \lim_{x\to\infty} \frac {\frac {\mathrm d}{\mathrm dx} g(x)}{\frac {\mathrm d}{\mathrm dx} \sqrt x} \\&= \lim_{x\to\infty} \frac{\frac 1 x}{\frac 1 {2\sqrt x}} \\ &= \lim_{x\to\infty} \frac 2 {\sqrt x} \\ &=0 \end{align}$$ 故 $g(n)=o(\sqrt n) = O\left(\sqrt n\right)$ 。 ### c 對於任意函數 $f(n)=O(F(n)), g(n)=O(G(n))$ ,存在 $c>0$ 和 $n_0>0$ 使得 $$\forall n>n_0, |f(n)|\leq|cF(n)| \wedge |g(n)|\leq|cG(n)|$$ 因此 $$\exists c>0, |f(n)g(n)| \leq c^2|F(n)G(n)|$$ 故得知 $f(n)g(n)=O(F(n)G(n))$ 。所以 $f(n)g(n)=O\left(n^2\sqrt n\right)=O\left(n^{2.5}\right)$ 。 ## 2 ### a 根據 Master Theorem: * 已知 $f(n)=O(n)$ * 存在 $\varepsilon=1$ 使得 $f(n)=\Omega(n^{\log_b a+\varepsilon})$ ,其中 $a=1,b=2$ 。 * 存在 $c=0.716023<1$ 使得 $af\left(\dfrac n b\right)\leq cf(n)$ ,因為 $$af\left(\dfrac n b\right)=f\left(\dfrac n 2\right)=O\left(\dfrac n 2\right)\leq O(n)=0.716023~f(n)=cf(n)$$ 故原式 $T(n)=\Theta(f(n))=\Theta(n)$ 。 ### b 因為 $\left\lceil\dfrac n 2\right\rceil - \left\lfloor \dfrac n 2\right\rfloor \leq1=O(1)$ ,故 $\left\lceil\dfrac n 2\right\rceil = \left\lfloor \dfrac n 2\right\rfloor + O(1)$ 。所以原式可以化為 $$ \begin{aligned} & T(n)= \begin{equation}\begin{cases} 2T\left(\left\lfloor \dfrac n 2\right\rfloor\right) + O(n)+O(1) &\mathrm{if}~n>1 \\ O(1) &\mathrm{if}~n=1 \end{cases}\end{equation} \\ \Longrightarrow~& T(n)= \begin{cases} 2T\left(\left\lfloor \dfrac n 2\right\rfloor\right) + O(n) &\mathrm{if}~n>1 \\ O(1) &\mathrm{if}~n=1 \end{cases}\end{aligned}$$ 根據 Master Theorem: * $f(n)=O(n)=\Theta\left(n^{\log_b a}\right)$ ,其中 $a=b=2$ 。 故 $T(n)=\Theta\left(n^{\log_2 2}\log n\right)=\Theta\left(n\log n\right)$ 。 ### c 理由同 2b ,原式可化為 $$ T(n)= \begin{equation}\begin{cases} 3T\left(\left\lfloor \dfrac n 2\right\rfloor\right)+O(n) & \mathrm{if}~n>1 \\ O(1) & \mathrm{if}~n=1 \end{cases}\end{equation}$$ 根據 Master Theorem: * $f(n)=O(n)=O\left(n^{\log_b a-\varepsilon}\right)$ ,其中 $a=3, b=2, \varepsilon=\log_2 3-1$ 。 故 $T(n)=\Theta\left(n^{\log_b a}\right)=\Theta\left(n^{\log_2 3}\right)$ 。 ### d 令 $n=2^k, S(k)=T\left(2^k\right)=T(n)$ ,可以推出 $$\begin{align} & T(n)=T(\sqrt n) +O(1) \\ \Longrightarrow ~& T\left(2^k\right)=T\left(2^{k/2}\right) + O(1) \\ \Longrightarrow ~& S(k)=2S\left(\dfrac k 2\right) + O(1)\end{align}$$ 亦即原式可以化為 $$S(k)=\begin{equation}\begin{cases}2S\left(\dfrac k 2\right)+O(1) &\text{if}~k>1 \\ O(1) &\text{if}~ k=1\end{cases}\end{equation}$$ 根據 Master Theorem: * $f(k)=O(1)=O\left(k^{\log_a b-\varepsilon}\right)$ ,其中 $a=b=2, \varepsilon=1$ 。 因此 $S(k)=\Theta\left(k^{\log_2 2}\right)=\Theta(k)$ ,亦即 $T(n)=\Theta(\log n)$ 。 ## 3 ### a 定義此 heap 的節點(最小的節點)為 $V_1$ 至 $V_{15}$ , $V_1$ 為 heap 頂端, $\forall i>1, V_i$ 的父節點為 $V_{\lfloor i/2\rfloor}$ 。為了方便敘述,令次小的節點為 $A$ 、再次小的的節點為 $B$ 。 顯然 $V_1$ 擁有最小值, $V_2$ 和 $V_3$ 之一擁有次小值。 * 令 $V_2$ 與 $V_3$ 比較,這裡假設較小者為 $A=V_2$ 。 在一個「比誰小」的遊戲中,$B$ 只可能輸給 $V_1$ 或 $A$ ,且在 heap 建造過程中只會輸給兩者之一恰一次。 * 若 $B$ 輸給 $V_1$ ,則 $B=V_3$ 。 * 若 $B$ 輸給 $A$ ,則 $B=V_4$ 或 $B=V_5$ 。 簡之, $B$ 必為 $V_3$ 、 $V_4$ 或 $V_5$ 其中之一。為了找出答案,可以: * 先令 $V_3$ 與 $V_4$ 比較,令較小者為 $Z$ 。 * 再令 $Z$ 與 $V_5$ 比較,較小者即為答案 $B$ 。 故只需要用到三次比較。考量所有情況, $B$ 可能為除了根和最底層以外的所有節點。 ### b 令第四小者的節點為 $C$ 。 $C$ 只可能輸給 $V_1$ 、 $A$ 或 $B$ 。因此 $C$ 必為該三節點其中之一的子節點。 因此具體找出 $C$ 的方法為: * 先找出 $A$ 。 * 再找出 $B$ 。 * 若 $A$ 與 $B$ 為 $V_1$ 的子節點,則 $C$ 為 $V_4$ 至 $V_7$ 其中之一,即第三層(根為第一層)。 * 若 $B$ 為 $A$ 的子節點,則 $C$ 可能為 $V_0$ 的另一個子節點、或 $A$ 的另一個子節點、或 $B$ 的兩個子節點其中之一。 考量所有的情況, $C$ 可能為 $V_2$ 至 $V_{15}$ 的任一節點,即除了根以外的所有其他節點。 ## 4 ### a 因為 $\forall i<j,S[i]>S[j]$ ,所以 $\forall i,S[i]+i\geq S[i+1]+(i+1)$ 。可以想像一個新陣列 $S[i]+i$ ,因為它是一個非嚴格遞減數列,故仍然可以使用單純的二分搜來找 $S[i]+i=0$ 。以下給出 pseudo code 的範例(陣列 index 刻意模仿題目從 $1$ 開始計算)。 ```javascript function judge(array) { let l = 1, r = array.length while (l < r) { let m = floor((l + r) / 2) if (array[m] + m <= 0) r = m else l = m + 1 } return array[l] + l == 0 } ``` ### b 在 $\forall i<j,S[i]\geq S[j]$ 的情況下,陣列 $S[i]+i$ 相當於未排序的陣列。判斷 $\exists i, S[i]+i=0$ 所需的複雜度顯然為 $\Omega(n)$ 。 下面給出一個遊戲的例子。假設玩家詢問任意索引 $i$ 的 $S[i]+i$ 值,我們可以總是回答 $716023$ (亦即 $\forall i, S[i]=716023-i$)。因為玩家無法藉由這個回答推斷其他索引 $S[j]+j\neq0$ 的可能,因此玩家至少要詢問 $n$ 次才能完成遊戲。複雜度 $\Omega(n)$ 。 ## 5 ### a 假設我有現成的 second mode 演算法 $A$ ,那我可以用 $A$ 和其他 $O(n)$ 內的步驟,來解決 element uniquness problem 。以下給出 pseudo code 和步驟。 ```javascript import function A(array) function is_unique(v, array) { let c = 0 for (e in array) if (e == v) c++ return c == 1 } function solve_element_uniqueness_problem(array) { let v = array[0] if (!is_unique(v, array)) return false // O(n) let n = array.length for (i=0; i<n; i++) array.append(v) // O(n) let s = A(array) // O(?) return is_unique(s, array) // O(n) } ``` 1. 先檢查陣列第一個元素 $v$ 是否只出現一次。若否,答案為假。這個步驟需要 $O(n)$ 。 2. 將 $n$ 個 $v$ 加入陣列中。 這個步驟需要 $O(n)$ 。 3. 呼叫 $A$ 演算法,得到陣列的 second mode 元素 $s$。時間複雜度待定。 4. 若 $s$ 只在陣列中出現一次,答案為真,否則為假。這個步驟需要 $O(n)$ 。 因為既成事實是 element uniqueness problem 的複雜度至低是 $\Omega\left(n\log n\right)$ ,所以可以肯定 $A$ 的複雜度至低為 $\Omega(n\log n)$ 。 ### b $N$-based 的 Radix sort 可以把排序複雜度降到 $O(\log_n n^4)O(n)=O(n)$ 。以下給出 psuedo code。 ```javascript function count_sort(array, exp) { let n = array.length // Declare an array of queue let q = queue[n] for (val in array) { let i = val / exp % n q[i].push(val) } let c = 0 for (i=0; i<n; i++) { while (!q[i].empty()) { array[c++] = q[i].front() q[i].pop() } } } function radix_sort(array) { let n = array.length // array is passed by reference count_sort(array, 1) // O(n) count_sort(array, n) // O(n) count_sort(array, n*n) // O(n) count_sort(array, n*n*n) // O(n) // Now array is sorted } ``` 排序好之後,就可以在 $O(n)$ 算出 second mode 。 ## 6 先講結論,答案為真,可以在 $O(n)$ 內判別 $$\min_{x\in S}\text{freq}(x)+\max_{x\in S}\text{freq}(x)>n\left(1-\frac 1 {\log n}\right)$$ 的真偽。 整個證明的大綱如下: * #1 若陣列中 distinct 元素少於等於兩個,答案恆真。 * #2 若陣列中 distinct 元素大於兩個,分兩情況。 * #2-1 若 $\displaystyle\max_{x\in S}\text{freq}(x)\leq n \left(1-\frac 2 {\log n}\right)$ ,答案恆假。 * #2-2 若 $\displaystyle\max_{x\in S}\text{freq}(x) > n \left(1-\frac 2 {\log n}\right)$ ,可以在 $O(n)$ 內判斷真偽。 ### 證明 首先判斷陣列的中 distinct 元素是否少於等於兩個,這可以在 $O(n)$ 內完成。以下給出 pseudo code 範例: ```javascript function is_distinct_value_leq_2(array) { let v0 = null, v1 = null for (i=1; i<array.length; i++) { // O(n) if (array[i] == array[i-1]) continue else if (v0 == null) { v0 = min(array[i], array[i-1]) v1 = max(array[i], array[i-1]) } else if(array[i] < array[i-1]) { if (array[i] != v0) return false } else { if (array[i] != v1) return false } } return true } ``` ### #1 如果陣列的中 distinct 元素少於等於兩個,則顯然 $$\min_{x\in S}\text{freq}(x)+\max_{x\in S}\text{freq}(x) = n ~\text{or}~ 2n$$ 答案為真。 ### #2 接下來考慮陣列中 distinct 元素多於兩個的情況。首先檢驗 $$\max_{x\in S}\text{freq}(x) > n\left(1-\frac 2 {\log n}\right)$$ 是否成立。 * 因為 $\displaystyle\frac n 2 \leq n\left(1-\frac 2 {\log n}\right)$ ,這可以透過 Boyer–Moore majority vote algorithm 在 $O(n)$ 之內判斷,並找出 $\displaystyle\max_{x\in S}\text{freq}(x)$ 的值。 以下給出 pseudo code 。 ```javascript function find_majority(array) { let maj = 0, c = 1; for (i=1; i<array.length; i++) { // O(n) if (array[maj] == a[i]) c++ else c-- if (c == 0) { maj = i c = 1 } } return array[maj]; } function find_frequency(array, val) { let c = 0 for (i in array) if (i == val) c++ // O(n) return c } // Queries if maxfreq(x)>n(1-2/log(n)) function judge(array) { let n = array.length let maj_candidate = find_majority(array) // O(n) // We can get the value of greatest frequency let max_freq = find_frequency(array, maj_candidate) // O(n) return max_freq > n * (1 - 2 / log(n)) } ``` ### #2-1 至此我們已經知道 $$\max_{x\in S}\text{freq}(x) \leq n\left(1-\frac 2 {\log n}\right)$$ 因為 $$\min_{x\in S}\text{freq}(x) \leq \dfrac 1 2\left(n-\max_{x\in S}\text{freq}(x)\right)$$ 故 $$\begin{align}\min_{x\in S}\text{freq}(x)+\max_{x\in S}\text{freq}(x) &\leq \dfrac 1 2\left(n-\max_{x\in S}\text{freq}(x)\right)+\max_{x\in S}\text{freq}(x) \\ &= \frac n 2 + \frac 1 2\left(\max_{x\in S}\text{freq}(x)\right) \\ &\leq\frac n 2 + \frac n 2 \left(1-\frac 2 {\log n}\right) \\ &= n\left(1-\frac 1 {\log n}\right)\end{align}$$ 得證答案為假。 ### #2-2 至此我們已經知道 $$\max_{x\in S}\text{freq}(x) > n\left(1-\frac 2 {\log n}\right)$$ 並且得出 $\displaystyle\max_{x\in S}\text{freq}(x)$ 的值,則只要計算 $\displaystyle\min_{x\in S}\text{freq}(x)$ 的值,就可以判斷原命題的真偽。以下證明給出 $O(n)$ 內的方法。 1. 因為 $$\max_{x\in S}\text{freq}(x) > n\left(1-\frac 2 {\log n}\right)$$ 則可以先將 majority 從陣列中去除,使得陣列的長度至多為 $\dfrac {2n} {\log n}$ 。顯然這個操作可以在 $O(n)$ 之內完成。 2. 已知對長度為 $n$ 的陣列可以在 $O(n\log n)$ 內排序完成;則對一個長度為 $\dfrac {2n} {\log n}$ 的陣列排序,可以在 $O\left(\dfrac{2n}{\log n}\log\dfrac{2n}{\log n}\right)=O(n)$ 內完成。以下給出在 $n$ 夠大 $(n>200)$ 的情況下的證明。 $$\begin{align}& n > \frac {2n}{\log n} \\ \Longrightarrow ~& \log n > \log \frac {2n}{\log n} \\ \Longrightarrow ~& 1 > \frac 1 {\log n}\log\frac{2n}{\log n} \\ \Longrightarrow ~& O(n)=2n>\frac{2n}{\log n}\log\frac{2n}{\log n}\end{align}$$ 3. 在排序剩餘的陣列元素之後,就可以在 $O(n)$ 內計算 $\displaystyle\min_{x\in S}\text{freq}(x)$ 的值。 至此,我們可以在 $O(n)$ 內判斷原命題的真偽。