# 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)$ 內判斷原命題的真偽。