演算法導論第二章練習
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章演算法
- 演算法導論FFT程式碼演算法FFT
- 演算法導論學習之補漏:高精度冪運算演算法
- 演算法導論第三十一(31)章數論演算法演算法
- 學演算法要讀《演算法導論》嗎?演算法
- 演算法導論學習之補漏:斐波那契數列演算法
- swift演算法練習筆記Swift演算法筆記
- 【演算法練習】(8)眾數演算法
- 【演算法導論】24.1 Bellman-Ford 演算法演算法
- python物件導向練習題01Python物件
- 史蒂芬斯與演算法導論之思演算法
- 遞迴與分治演算法練習遞迴演算法
- matlab練習程式(Sinkhorn演算法)Matlab演算法
- 演算法練習記錄(24.10.5)演算法
- ”回溯演算法“框架及練習題演算法框架
- 演算法導論 3.2-7 共軛數演算法
- 演算法導論_第七章_快速排序演算法排序
- 演算法導論C語言實現: 演算法基礎演算法C語言
- 人工智慧導論學習筆記人工智慧筆記
- 演算法導論_第四章_分治策略演算法
- 演算法導論_第六章_堆排序演算法排序
- 演算法導論16.1 活動選擇問題演算法
- 演算法導論-動態規劃-鋼條切割演算法動態規劃
- 第二章 辯論的架構架構
- 博弈論專練