演算法導論第二章練習
2.1練習
2.1-1
(1) 31 41 59 26 41
(2) 31 41 59 26 41
(3) 26 31 41 59 41
(4) 26 31 41 41 59
需要注意的是,這裡的原陣列的後項41在排序後仍在前項41的後面
2.1-2
按降序排序,只需要在迴圈提內部的if判斷中將 < 改為 > 即可,判斷每次插入的數字是否比被插入的陣列中的元素大,若大,則開始執行
2.1-3
public static int searchNum(int[] arr,int num) {
for(int i = 0;i < arr.length;i++) {
if(arr[i] == num) {
return i;
}
}
return (Integer) null;
}
迴圈不變式:在迴圈的每次迭代開始前,A[0...i-1]中不包含值為v的成員
初始化:在第一次迴圈開始之前,即當賦值i = 0時,陣列A[0..-1]中不包含元素,所以顯然所查詢的數字不在其中,所以迴圈不變式成立。
保持:假設本次迭代時i = K,那麼顯然若要執行本次迭代,A[0..k-1]不包含所查詢的數字,即迴圈不變式成立,那麼如果可以執行下次迭代,A[k] 必不等於 v,那麼A[0..k]中也不包含v,那麼迴圈不變式仍然成立。
終止:當i = arr.length時,迴圈結束,或在某次迴圈時A[i] == v終止,當第一種結果出現時,A[0..arr.length - 1]滿足迴圈不變式,即數字不在陣列中;當第二種結果出現時,A[0..k-1]滿足迴圈不變式,即陣列下標k位置為所查詢的數字
2.1-4
public static int[] addBirnaryNum(int[] arrA,int[] arrB) {
int n = arrA.length;
int[] arrC = new int[n+1];
int c = 0;//進位
for(int i = n-1;i >= 0;i--) {
int addBitResult = arrA[i] + arrB[i] + c;
if(addBitResult > 1) { //判斷是否有進位出現
c = 1;
}
if(addBitResult == 2 || addBitResult == 0) { //判斷當前位的情況
arrC[i+1] = 0;
}else {
arrC[i+1] = 1;
}
}
if(c == 1) {
arrC[0] = 1;
}else {
arrC[0] = 0;
}
return arrC;
}
2.2練習
2.2-1
Θ(n³)
2.2-2
(1)
public static void selectionSort(int[] arr) {
int minmumIndex;
int minmum;
for(int i = 0;i < arr.length - 1;i++) {
minmumIndex = i;
minmum = arr[i];
for(int j = i+1;j < arr.length;j++) {
if(arr[j] < minmum) {
minmumIndex = j;
}
}
int temp = arr[minmumIndex];
arr[minmumIndex] = arr[i];
arr[i] = temp;
}
}
(2)迴圈不變式是當迴圈迭代每次開始之前,A[0..k-1]已按序排列
(3)因為在第n-1個元素迭代時,已經比較了第n-1個元素和第n個元素的大小,所以當該次迭代執行完成後,陣列已經是排完序了
(4)最好的情況:Θ(n²)
最壞的情況:Θ(n²)
2.2-3
平均需要查詢 n/2個元素,最壞需要查詢n個元素
平均情況下執行時間:Θ(n)
最壞情況下執行時間:Θ(n)
2.2-4
我們可以首先設計一個針對該問題的一個特定輸入,使得這個特定輸入是最好的情況,然後不斷修改演算法,使其針對該特列的執行時間達到最佳
2.3練習
2.3-1
(1)劃分成單個元素 3 41 52 26 38 57 9 49
(2)解決兩兩排序再合併再排序在合併
3,41 26,52 38,57 9,49
3,26,41,52 9,38,49,57
3,9,26,38,41,52,57
2.3-2
public static void combine(int[] arr,int p,int q,int r) {
int n1 = q-p+1;
int n2 = r-q;
int[] arr1 = new int[n1];
int[] arr2 = new int[n2];
for(int i = 0;i < n1;i++) {
arr1[i] = arr[p+i];
}
for(int j = 0;j < n2;j++) {
arr2[j] = arr[q+1+j];
}
int i = 0;
int j = 0;
for(int k = p; k <= r;k++) {
if(arr1[i] <= arr2[j]) {
arr[k] = arr1[i];
i += 1;
if(i == n1) {
for(;j < n2;j++) {
arr[k+1] = arr2[j];
k += 1;
}
break;
}
}else {
arr[k] = arr2[j];
j += 1;
if(j == n2) {
for(;i < n1;i++) {
arr[k+1] = arr1[i];
k += 1;
}
break;
}
}
}
}
2.3-3
證明:
當n = 2時,
T(n)= nlgn = 2*lg2 = 2
∴ 成立
當n = 2^k
假設 T(n/2)= n/2 * lg(n/2) 成立
∵ T(n)= 2T(n/2)+ n
∴ T(n)= n* lg(n/2) + n
= nlgn - n + n
= nlgn
∴ T(n)= nlgn
2.3-4
public static void insert(int[] arr,int p,int q) {
int i;
int key = arr[q];
for(i = q-1;arr[i] >= key;i--) {
arr[i+1] = arr[i];
}
arr[i+1] = key;
}
public static void divideAndConquerInsertionSort(int[] arr,int p,int q) {
if(p < q){
divideAndConquerInsertionSort(arr,p,q-1);
insert(arr,p,q);
}
}
∴ T(n)= T(n-1)+ cn
2.3-5
遞迴實現
public static int binarySearch(int[] arr,int p,int r,int num) {
if(p <= r) {
int q = (p+r)/2;
if(arr[q] == num) {
return q;
}else if(arr[q] > num) {
return binarySearch(arr,p,q-1,num);
}else {
return binarySearch(arr,q+1,r,num);
}
}
return -1;
}
迭代實現
public static int binarySearch2(int[] arr,int p,int r,int num) {
int q;
while(p <= r) {
q = (p+r)/2;
if(arr[q] == num) {
return q;
}else if(arr[q] > num) {
r= q-1;
}else {
p = q+1;
}
}
return -1;
}
∵ T(n) = T(n/2)
∴ n/2^i = 1
∴ i = lgn
∴ T(n)= c(lgn + 1) = Θ(lgn)
2.3-6
程式碼實現
public static int binarySearch(int[] arr, int p, int r, int num) {
int mid = 0;
while (p <= r) {
mid = (p + r) / 2;
if (arr[mid] == num) {
break;
} else if (arr[mid] > num) {
r = mid - 1;
} else {
p = mid + 1;
}
}
return mid;
}
public static void insertionSort(int[] arr) {
for(int i = 1;i < arr.length;i++) {
int j = i-1;
int index = binarySearch(arr,0,j,arr[i]);
int temp = arr[i];
if(arr[index] == arr[i]) {
for(;j >= index;j--) {
arr[j+1] = arr[j];
}
}else if(arr[index] > arr[i]) {
for(;j > index - 1;j--) {
arr[j+1] = arr[j];
}
arr[index] = temp;
}else {
for(;j > index;j--) {
arr[j+1] = arr[j];
}
arr[index + 1] = temp;
}
}
}
在該二分查詢的方法中,做了修改,如果沒有查詢到數字,則返回放置時與它最近的一個元素的下標,也就是最後一次mid的位置,如果有這個元素就返回找到元素的下標。
然後在插入排序中進行判斷返回的下標在陣列中的數字是否與插入元素的值相等,如果相等,則在該元素的後面插入,如果大於插入元素,則在該下標前插入元素,如果小於,則該下標之後插入元素。
但是不難看出,因為需要元素移位,那麼迴圈內部必定巢狀迴圈,那麼最後T(n)= Θ(n²),所以不可能
2.3-7
public static boolean findNumInTwoNumSum(int[] arr,int num) {
int subNum;
int result;
for(int i = 0;i < arr.length - 1;i++) {
subNum = num - arr[i];
result = binarySearch2(arr,0,arr.length - 1,subNum);
if(result != i && result != -1) {
return true;
}
}
return false;
}
思路就是,用所給的數逐個減陣列中的元素,然後用二分查詢找減後的數,然後存在,即S中存在兩數之和剛好為x
相關文章
- 演算法導論第二章思考題演算法
- 演算法導論第二章筆記演算法筆記
- 演算法導論第三章練習演算法
- 第二章課後練習題
- 演算法導論課後習題解答 第一部分 練習1.1-1->1.1-5演算法
- 演算法練習演算法
- 演算法導論-第6章演算法
- 學演算法要讀《演算法導論》嗎?演算法
- python物件導向練習題01Python物件
- swift演算法練習筆記Swift演算法筆記
- 【演算法練習】(8)眾數演算法
- 演算法練習記錄(24.10.5)演算法
- matlab練習程式(Sinkhorn演算法)Matlab演算法
- 演算法導論 3.2-7 共軛數演算法
- 遞迴與分治演算法練習遞迴演算法
- ”回溯演算法“框架及練習題演算法框架
- 人工智慧導論學習筆記人工智慧筆記
- Python-100 練習題 01 & 列表推導式Python
- 《軟體工程導論》課後習題答案軟體工程
- 演算法導論 3.1-8 記號擴充套件演算法套件
- 博弈論專練
- 演算法練習--LeetCode--54. Spiral Matrix 100%演算法LeetCode
- 演算法練習題1-括號序列演算法
- LLM並行訓練4-megascale論文學習並行
- 程式碼隨想錄演算法訓練營第64天 | 圖論:Floyd 演算法+A * 演算法演算法圖論
- markdown 使用練習練習
- 02142資料結構導論複習筆記資料結構筆記
- 演算法導論學習--紅黑樹詳解之刪除(含完整紅黑樹程式碼)演算法
- 演算法練習--LeetCode--29. Divide Two Integers: 100%演算法LeetCodeIDE
- LeetCode演算法練習——深度優先搜尋 DFSLeetCode演算法
- 【方法論】機器學習演算法概覽機器學習演算法
- 圖論與圖學習(二):圖演算法圖論演算法
- 前端切圖練習,仿嗶哩嗶哩導航欄前端
- 動態規劃-隔鋼條-演算法導論-2021/1/1動態規劃演算法
- 工程學導論
- 新手練習:Python練習題目Python
- 演算法練習--LeetCode--17. Letter Combinations of a Phone Number: 100%演算法LeetCode
- 笨辦法學C 練習38:雜湊演算法演算法