# 演算法作業03 ## 第1題:Insertion Sort ### 請依據課本推導方式,當5個數字用insertion sort排序,data movement的平均值為多少? :::info 從$j$開始搬運一次的平均data movement $\frac{2}{j}+\frac{3}{j}+\frac{4}{j}+ \cdots+\frac{j+1}{j}=\frac{j+3}{2}$ ::: :::info $X=\sum\limits_{j=2}^{n}\frac{j+3}{2}=\frac{(n+8)(n-1)}{4}$ ::: :::success $n=5$ $X=\frac{(5+8)(5-1)}{4}=13$ $Ans:13$ ::: ### 請使用insertion sort排序 6,4,1,3,5。在四個回合中,每回合的data movement數量為何?總共的data movement數量為何? #### 第一回合 :::info 初始的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 6 | <font color="#f00">4</font> | 1 | 3 | 5 | 1. $4丟進暫存X$ 2. $a_0>X,6往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | <font color="#f00">6</font> | <font color="#f00">6</font> | 1 | 3 | 5 | 因為$j<0$所以跳出迴圈 3. $暫存X存在a_0$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | <font color="#f00">4</font> | 6 | 1 | 3 | 5 | $data\ movement:3$ $sum\ of\ data\ movement:3$ ::: #### 第二回合 :::info 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 4 | 6 | <font color="#f00">1</font> | 3 | 5 | 1. $1丟進暫存X$ 2. $a_1>X,6往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 4 | <font color="#f00">6</font> | <font color="#f00">6</font> | 3 | 5 | 3. $a_0>X,4往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | <font color="#f00">4</font> | <font color="#f00">4</font> | 6 | 3 | 5 | 因為$j<0$所以跳出迴圈 4. $暫存X存在a_0$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | <font color="#f00">1</font> | 4 | 6 | 3 | 5 | <font color="#900"> $data\ movement:4$ $sum\ of\ data\ movement:7$ </font> ::: #### 第三回合 :::info 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | 4 | 6 | <font color="#f00">3</font> | 5 | 1. $3丟進暫存X$ 2. $a_2>X,6往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | 4 | <font color="#f00">6</font> | <font color="#f00">6</font> | 5 | 3. $a_1>X,4往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | <font color="#f00">4</font> | <font color="#f00">4</font> | 6 | 5 | 因為$X>a[j]$所以跳出迴圈 4. $暫存X存在a_1$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | <font color="#f00">3</font> | 4 | 6 | 5 | <font color="#900"> $data\ movement:4$ $sum\ of\ data\ movement:11$ </font> ::: #### 第四回合 :::info 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | 3 | 4 | 6 | <font color="#f00">5</font> | 1. $5丟進暫存X$ 2. $a_3>X,6往後移$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:----:|:----:| | 1 | 3 | 4 | <font color="#f00">6</font> | <font color="#f00">6</font> | 因為$X>a[j]$所以跳出迴圈 3. $暫存X存在a_3$ 現在的序列: | a[0] | a[1] | a[2] | a[3] | a[4] | |:----:|:----:|:----:|:---------------------------:|:----:| | 1 | 3 | 4 | <font color="#f00">5</font> | 6 | <font color="#900"> $data\ movement:3$ $sum\ of\ data\ movement:14$ </font> ::: :::success $ans:14$ ::: ## 第2題:Binary Search ### 請參考投影片25頁與26頁,算出15個有序數列使用Binary Search,平均的比對次數為何? :::info 樹高 $\lfloor{log_{2}n}\rfloor+1$ ::: :::info $A(N)= \frac{1}{2n+1} ($<font color="#090">$\sum\limits_{i=1}^{k}i2^{i-1}$</font>+<font color="#f00">$k(n+1)$</font>$),where\ k=\lfloor{log_{2}n}\rfloor+1$ $\sum\limits_{i=1}^{k}i2^{i-1} = 2^{k}(k-1)+1$ $A(N)= \frac{1}{2n+1}($<font color="#f00">$2^{k}(k-1)+1$</font>$+k(n+1)),where\ k=\lfloor{log_{2}n}\rfloor+1$ ::: :::success $k_{n=15}=\lfloor{log_{2}15}\rfloor+1=4$ $A(15)= \frac{1}{2\times15+1}(2^{4}(4-1)+1+4(15+1))$ $A(15)=\frac{1}{31}\times(16\times3+1+4\times16)$ $A(15)=\frac{1}{31}\times(48+1+64)$ $A(15)=\frac{1}{31}\times(113)$ $A(15)=\frac{113}{31}\simeq3.645$ $Ans:\frac{113}{31}\simeq3.645$ ::: ## 第3題:完全平方數 ### 解題思路 第一個小於2147483647的完全平方數是$46340\times 46340$ 先判斷是不是在範圍內 找到第一個大於等於$\sqrt[2]{num}$的$l$ 然後判斷$l \times l$是否等於$num$ ### 程式碼 ```cpp= class Solution { public: bool isPerfectSquare(int num) { if(num>46340*46340) { return 0; } int l=1,r=46340,mid; while(l<=r) { mid=(l+r)/2; if(mid*mid>=num) { r=mid-1; } else { l=mid+1; } } return l*l==num; } }; ``` ### 測試輸出輸入的畫面截圖 ![image](https://hackmd.io/_uploads/BkbtIBrTT.png) ### 花費時間 7分鐘 ### 完成程度 完全自己解出 ## 第4題 ### 解題思路 二分搜找第一個大於他的值 然後再判斷是不是超出去了 ### 程式碼 ```cpp= class Solution { public: char nextGreatestLetter(vector<char>& letters, char target) { int l=0,r=letters.size()-1,mid; while(l<=r) { mid=(l+r)>>1; if(letters[mid]>target) { r=mid-1; } else { l=mid+1; } } return l>=letters.size()?letters[0]:letters[l]; } }; ``` #### 如果用STL可以秒解:D ```cpp= class Solution { public: char nextGreatestLetter(vector<char>& letters, char target) { int l = upper_bound(letters.begin(),letters.end(),target) - letters.begin(); return l>=letters.size()?letters[0]:letters[l]; } }; ``` ### 測試輸出輸入的畫面截圖 ![image](https://hackmd.io/_uploads/rkqSarSp6.png) ### 花費時間 4分鐘 ### 完成程度 完全自己解出 ## 第5題 ### 解題思路 二分搜去找mid那點的斜率 分成三個可能 1. / $l<=mid<=r$ 2. \ $l>=mid>=r$ 3. ^ $l<=mid>=r$ 如果數量不到三個就一個一個看 ### 程式碼 ```cpp= class Solution { public: int peakIndexInMountainArray(vector<int>& arr) { int l=0,r=arr.size()-1,mid; while(r-l>=3) { mid=(l+r)>>1; if(arr[mid+1]>arr[mid]&&arr[mid]>arr[mid-1]) { l=mid+1; } else if(arr[mid-1]>arr[mid]&&arr[mid]>arr[mid+1]) { r=mid-1; } else { return mid; } } int ma=arr[l],in=l; for(int i=l+1;i<=r;i++) { if(arr[i]>ma) { ma=arr[i]; in=i; } } return in; } }; ``` ### 測試輸出輸入的畫面截圖 ![image](https://hackmd.io/_uploads/S1e8MDISTp.png) ### 花費時間 14分鐘 ### 完成程度 完全自己解出 ## 第6題 ### 解題思路 跟上次作業求最大值的二分搜概念一樣 把如果是前半段比較大的就把左界拉過去 而右界基本上就是一直縮 加上判斷是不是最尾端再輸出就好 ### 程式碼 ```cpp= class Solution { public: int findMin(vector<int>& nums) { int l=0,r=nums.size()-1,mid; while(l<=r) { mid=(l+r)>>1; if(nums[mid]>=nums[0]) { l=mid+1; } else { r=mid-1; } } return l>=nums.size()?nums[0]:nums[l]; } }; ``` ### 測試輸出輸入的畫面截圖 ![image](https://hackmd.io/_uploads/r1Vd58Hpp.png) ### 花費時間 8分鐘 ### 完成程度 完全自己解出 ## 第7題 已填