一、遞迴與分治策略
一、概述
1.設計思想
遞迴:直接或間接地呼叫自身
分治法:將一個規模為n的難以解決的大問題劃分成k個規模較小的子問題,這些子問題相互獨立且與原問題性質和解法類似,遞迴求解這些子問題,再合併子問題的解得到原問題的解
2.求解過程
(1)劃分(平衡子問題、獨立子問題)
(2)求解子問題(遞迴、迴圈)
(3)合併(對演算法效率影響較大)
二、例題總結
(前面5個問題運用遞迴策略,後面運用分治策略)
1.階乘函式
遞迴定義式:
遞迴實現:
2.Fibonacci數列
遞歸定義式:
遞迴實現:
演算法改進:避免重複計算,自下而上計算,由f(0)和f(1)算出f(2)...
3.排列生成問題
遞迴關係:
(1)將n個元素看成由兩部分組成:第一部分是第一個元素,第二部分是後面所有元素;
(2)將生成排列過程看作兩步:第一步求所有可能出現在第一個位置的元素,即把第一個元素與後面所有元素交換;第二步固定第一個元素,求後面所有元素的排列。
Perm(R)的遞迴演算法實現:
4.整數劃分問題
將正整數n表示成一系列正整數之和,稱這種表示為正整數n的劃分,稱n的不同劃分個數為正整數n的劃分數,記作p(n)
5.Hanoi塔問題
6.折半查詢
7.大整數乘法(演算法思想>程式碼)
8.Strassen矩陣乘法
9.棋盤覆蓋
棋盤覆蓋問題(board cover problem)要求用4中不同形狀的L型骨牌覆蓋給定棋盤上除特殊方格以外的所有方格,且任何兩個L型骨牌不得重複覆蓋。
分治策略:將棋盤劃分為大小相等的子棋盤,並且每個子棋盤均包含一個特殊方格,從而將原問題分解為規模較小的子問題。具體步驟如下:將2k*2k棋盤劃分為4個2k-1*2k-1子棋盤,特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤無特殊方格,用一個L型骨牌覆蓋這3個較小棋盤的匯合處,又得到3個具有特殊方格的子棋盤,從而將原問題轉換為4個較小規模的棋盤覆蓋問題。遞迴使用這種分割,直至棋盤簡化為1*1棋盤。
演算法實現:
演算法分析:
10.歸併排序
按記錄在序列中的位置對序列進行劃分,穩定的演算法
演算法思想:
將待排序序列劃分為長度大致相等的兩個子序列,若子序列長度為1,則劃分結束,否則繼續執行劃分,最後得到n個長度為1的有序子序列
不斷進行兩兩合併,用歸併演算法將它們排序;
如此繼續下去,直至得到一個長度為n的有序序列。
演算法實現:設將兩個相鄰有序子序列r[s]~r[m]和r[m+1]~r[t]合併為一個有序序列r1[s]~r1[t],函式Merge實現合併操作。
演算法分析:
11.快速排序
按照記錄的值對序列進行劃分,不穩定的演算法
演算法思想:
演算法實現:
演算法分析:
12.最近點對問題
給定平面上n個點,找其中的一對點,使得在n個點組成的所有點對中,該點對間的距離最小。(只找其中一對最近點即可)
演算法思想:
(1)劃分:將集合S劃分為兩個子集S1和S2,根據平衡子問題原則,每個子集大約包含n/2個點,設最近點對為Pi和Pj,有以下三種情況:
①Pi和Pj均在S1中;
②Pi和Pj均在S2中;
③Pi在S1中,Pj在S2中。
(2)求解子問題:情況①②可遞迴求解:l為S中各點x座標的中位數,垂線x=l將S劃分為S1和S2,遞迴地在S1和S2中求解最近點對問題,得到最近距離d=min{d1,d2};
情況③:設P1是S1中距離垂線l在長度d之內的所有點集,P2是S2中距離垂線l在長度d之內的所有點集;
將P1和P2中的點依其y座標值排序,設p(x,y)是y座標最小的點(P1和P2都有可能);
依次處理P1,P2中的點,在y座標區間[y,y+d]內最多選出8個候選點,計算它們和點p之間的距離,最後得到最近距離d3;
(3)合併:比較d1、d2和d3,選取最小距離作為原問題的解。
演算法實現:
演算法分析:
13.迴圈賽日程表
演算法思想:
演算法實現: