遞迴與分治演算法練習
最近剛學習演算法設計與分析的課程,所用教材是清華大學出版社王曉東編著的《演算法設計與分析》。一道關於遞迴與分治演算法的練習題如下:
剛拿到題目覺得這題目似乎和遞迴分治沒有什麼關係,但是O(1)的空間複雜度,以及O(n)的時間複雜度度就限制瞭解決方法,也就是分治和遞迴。(使用python語言只需幾行,用切片即可完成,這裡附上極其弱智的程式碼)
def exchange(a,k):
a=a[k:]+a[0:k]#列表切片
return a
ls=[1,2,3,4,5,6,7]
print(exchange(ls,4))
現在我們來思考這個遞迴分治演算法。
開始前先說明一下變數含義:
start:左邊子陣列開始位置下標
sep:分割位置下標(左邊子陣列結束位置下標)
end:右邊子陣列結束位置下標
首先,是最簡單的情況,相信大家一定能想到,如果兩個子陣列長度相等,直接遍歷子陣列的長度,寫上三行交換程式碼就可以解決了。(在這就不給出圖例了,簡單腦補一下即可)
接下來,就是剩餘兩種情況:分別是左邊子陣列長度>右邊子陣列長度以及左邊子陣列長度<右邊子陣列長度。我的基本想法就是長度小的一邊可以直接交換到位,長度長的一邊分成兩部分,一部分就是長度短的子陣列長度,另一部分就是剩餘部分長度。即:
長陣列用和短陣列相同長度的元素和短陣列元素一一交換,長陣列剩餘元素不動。第一次交換完成後短陣列已經直接到位,接下來處理剩餘元素長度即可,從而問題規模縮小,使用分治遞迴可以解決。
下面圖例都是以這個陣列為例{1,2,3,4,5,6,7}(紅色字型表示已經到位的元素)
圖一(start=0,sep=4,end=6):
判斷是左邊大於右邊;長度為2的兩對交換。1,2和6,7互換位置;6,7到位。start前進2位(start=2),sep不變,end也不變。
判斷是左邊大於右邊;1,2和6,7互換位置;6,7,1,2到位。start再前進2位(start=4),sep不變,end也不變。
判斷是左邊小於右邊;5和3互換位置;6,7,1,2,3到位。start前進1位(start=5),sep增1(sep=5),end不變。
判斷是左邊等於右邊;5和4直接交換位置,所有元素全部到位。
圖二(start=0,sep=1,end=6):
判斷是左邊小於右邊;長度為2的兩對交換。1,2和3,4互換位置;3,4到位。start前進2位(start=2),sep前進1位(sep=3),end也不變。
判斷是左邊小於右邊;1,2和5,6互換位置;3,4,5,6到位。start再前進2位(start=4),sep前進2位(sep=5),end也不變。
判斷是左邊大於右邊;5和3互換位置;6,7,1,2,3到位。start前進1位(start=5),sep增1(sep=5),end不變。
判斷是左邊等於右邊;2和1直接交換位置,所有元素全部到位。
接下來是程式碼呈現:
public static void exchange(int a[],int start,int sep,int end)
{ 鄭州婦科醫院
int t;
// 左邊子陣列長度 = 右邊子陣列長度
if(end-sep==sep-start+1)
{
for (int i = start; i <=sep; i++)
{
t=a[i];
a[i]=a[i+sep-start+1];
a[i+sep-start+1]=t;
}
}
// 左邊子陣列長度 > 右邊子陣列長度
if(end-sep
{
for(int i=end;i>=sep+1;i--)
{
t=a[i];
a[i]=a[i-(sep-start+1)];
a[i-(sep-start+1)]=t;
}
// start=start+end-sep;
exchange(a, start+end-sep, sep, end);
//遞迴呼叫exchange方法
// exchange(a, start, sep, end);
}
// 左邊子陣列長度 < 右邊子陣列長度
if(end-sep>sep-start+1)
{
for(int i=start;i<=sep;i++)
{
t=a[i];
a[i]=a[i+sep-start+1];
a[i+sep-start+1]=t;
}
// start=sep+1;
// sep=sep+sep-start+1;
exchange(a, sep+1, sep+sep-start+1, end);
//遞迴呼叫exchange方法
exchange(a, start, sep, end);
}
}
左邊子陣列長度 >右邊子陣列長度:
左右兩邊交換,中間不動,交換後左邊部分完成,右邊遞迴,*start前進短的子陣列的長度個單位,*短的子陣列長度=end-sep,所以有start=start+end-sep;sep不變,end也不變。
左邊子陣列長度 <右邊子陣列長度:
左邊中間交換,右邊不動,交換後左邊部分完成,右邊遞迴,start前進短的子陣列的長度個單位,短的子陣列長度=sep-start+1,所以有start=start+sep-start+1=sep+1。sep也前進短子陣列長度個單位,sep=sep+sep-start+1;end不變。
測試:
int a[]= {10,2,8,3,5,4,7,1};
...
exchange(a, 0,4,a.length-1);
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2679213/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 遞迴 & 分治演算法深度理解遞迴演算法
- 計算機演算法設計與分析——遞迴與分治策略(一)計算機演算法遞迴
- 計算機演算法設計與分析筆記(二)——遞迴與分治計算機演算法筆記遞迴
- java常見遞迴練習題Java遞迴
- 二叉樹遞迴練習二叉樹遞迴
- 歸併排序(C++_分治遞迴)排序C++遞迴
- 演算法小專欄:遞迴與尾遞迴演算法遞迴
- 【演算法】2 由股票收益問題再看分治演算法和遞迴式演算法遞迴
- 演算法學習-遞迴排序演算法遞迴排序
- 揹包問題的遞迴與非遞迴演算法遞迴演算法
- 資料結構與演算法學習總結--遞迴資料結構演算法遞迴
- Java程式設計基礎24——遞迴練習Java程式設計遞迴
- 反轉連結串列系列題練習遞迴遞迴
- 遞迴程式的漸近分析(以分治為例)遞迴
- 遞迴演算法遞迴演算法
- 資料結構與演算法:遞迴資料結構演算法遞迴
- 二十一、氣泡排序演算法——JAVA實現(遞迴與非遞迴)排序演算法Java遞迴
- 二叉樹——後序遍歷的遞迴與非遞迴演算法二叉樹遞迴演算法
- 演算法學習-CDQ分治演算法
- 遞迴演算法轉換為非遞迴演算法的技巧遞迴演算法
- 【演算法】遞迴演算法演算法遞迴
- Java遞迴演算法Java遞迴演算法
- 遞迴演算法要素遞迴演算法
- 資料結構與演算法(十一)——演算法-遞迴資料結構演算法遞迴
- 快速排序(遞迴及非遞迴演算法原始碼)排序遞迴演算法原始碼
- 前端學習 資料結構與演算法 快速入門 系列 —— 遞迴前端資料結構演算法遞迴
- 演算法初探--遞迴演算法演算法遞迴
- 「演算法之美系列」遞迴與回溯(JS版)演算法遞迴JS
- 淺談遞迴演算法遞迴演算法
- JavaScript演算法之遞迴JavaScript演算法遞迴
- 每日一演算法:遞迴演算法遞迴
- 遞迴與goto (轉)遞迴Go
- 迭代與遞迴--你被遞迴搞暈過嗎?遞迴
- 順序表應用7:最大子段和之分治遞迴法遞迴
- 每天刷個演算法題20160521:二叉樹高度(遞迴與非遞迴)演算法二叉樹遞迴
- Java資料結構與演算法--遞迴和回溯Java資料結構演算法遞迴
- 遞迴演算法程式設計整數因子分解問題的遞迴演算法遞迴演算法程式設計
- Java遞迴演算法的使用Java遞迴演算法