实验2 递归和分治法(二分查找)
1.遞歸的基本思想
(1)何為遞歸?
遞歸顧名思義就是′遞′和′歸′
👀所謂的‘遞’也就是“向下遞去”,這個問題可以分解為若干個且形式相同的子問題,這些子問題可以使用相同的思路來解決。
👀所謂的‘歸’也就是“歸來的意思”,什么時候歸來?所以涉及到了臨界點,也就是‘遞’中的分解終止條件。
(2)遞歸的工作原理?
💦根據以上分析可以發現這個流程和棧的工作原理一致,遞歸調用就是通過棧這種數據結構完成的。整個過程實際上就是一個棧的入棧和出棧問題。然而我們并不需要關心這個棧的實現,這個過程是由系統來完成的。
(3)遞歸的慣性解題思路
遞歸本質上類似數學中的歸納法,但又有所不同。(遞歸是從F(n)倒推到F(1),然后在F(1)回溯到F(n);相比于歸納法多了一步。)
(4)遞歸的三要素
💥1、縮小問題規模
👀這個縮小問題規??梢愿鶕w納法先進行回推,比如讓求S(n),我們可以先求當n=1的解決方法,再求n=2時的解決方法…一直歸納到S(n);這樣我們就可以推導出關系式S(n)=S(n-1)+?
💥2、明確遞歸終止條件
👀遞歸既然有去有回,就必須有一個臨界條件,當程序到達這個臨界值就必須進行歸來;否者就肯定會造成無線遞歸下去!
💥3、給出遞歸終止時的處理辦法
👀根據上文中闡述的遞歸的工作原理,遞歸是通過棧來實現的;當程序到達臨界條件時,后續必須進行出棧。了解函數的壓棧和出棧過程,函數出棧也就是返回到上一個函數的調用處繼續執行。例如求解F(n),遞推式是F(n)=F(n-1)+F(n-2),終止條件F(1)=1,F(0)=0;它的流程是每次進行壓棧F(n-1)、F(n-2),當達到終止條件時進行函數的出棧,那么返回什么值呢?根據遞歸的倒數第一步F(2)=F(1)+F(0)所以返回的是F(1)+F(0),也就是1.
2.分治法的基本思想
對于一個規模為n的問題,若該問題可以容易地解決(比如說規模n較小)則直接解決,否則將其分解為k個規模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞歸地解這些子問題,然后將各子問題的解合并得到原問題的解。這種算法設計策略叫做分治法?!竞唵瘟苏f就是“分而治之”】
3.分治法所能解決的問題一般具有以下幾個特征:
(1)該問題的規??s小到一定的程度就可以容易地解決
(2)該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質。
(3)利用該問題分解出的子問題的解可以合并為該問題的解;
(4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題
4.解決該問題的步驟
問題:給定N個數據和待查找的數據x,采用二分查找算法來搜索x,輸出x在N個數據中的位置
(1)解題思路
取數組中間索引mid=(begin+end)/2,比較待搜索值與中間值,如果待搜索值>中間值,則去中間索引的右邊繼續搜索,反之去左邊;就這樣循環下去,直到搜索到該值或者begin<end時終止程序。
(2)分析以上算法思想的弊端
根據它的 int mid = (begin+end)/2 ,我們可以推算二分算法適用于什么場景;
假設一個數組為arr[1,2,3,4,5…,98,99,100] ,我們要找尋1這個值,那么需要幾次找到呢?看下面的運行結果
可以看出經歷了六次循環調用才找到;如果找value=50,那么一次就能成功!所以這個調用多少次與mid的取值也有很大關系;
5.對二分查找算法進行優化
分析mid=(begin+end)/2,看出begin、end無法做出改變,那么只有對1/2進行改動;mid=begin + (begin+end) / {(value-arr[begin])/(arr[end]-arr[begin])},根據上文中找尋1,我們可以算出mid = 1。
根據上文進行分析,這個插值查找算法是對二分查找算法的改進。mid=begin + (begin+end) / {(value-arr[begin]) / (arr[end]-arr[begin])},這也就是插值查找算法。
- 優化思路如下:
- 上述二分思想f = 1 / 2 (f為變化率)
- 將mid隨著x值的大小做不斷變化 f = (x - arr[begin]) / (arr[end] - arr[begin])
- 則 mid=f * (begin+end)
6.代碼與結果展示
(1)非遞歸方式
(4)插值優化
/*** int mid = begin + (begin + end) * [(x - arr[begin]) / (arr[end] - arr[begin])];* @param arr 待搜索數組* @param begin 頭索引* @param end 尾索引* @param x 待搜索值* @return 對應的下標*/public static int binarySearch4(int[] arr, int begin, int end, int x) {if (begin > end || x < arr[begin] || x > arr[end]) {return -1;}int mid = begin + (begin + end) * (x - arr[begin]) / (arr[end] - arr[begin]);if (arr[mid] > x) {return binarySearch4(arr, begin, mid - 1, x);} else if (arr[mid] < x) {return binarySearch4(arr, mid + 1, end, x);} else {return mid;} }7.測試結果
待搜索數組:int[] arr = {1, 3, 4, 5, 8, 11, 23, 77};
當搜索x = 3時,結果如下
當搜索x = -11時,結果如下
當搜索x = 156時,結果如下
當搜索x =77時,結果如下
總結
以上是生活随笔為你收集整理的实验2 递归和分治法(二分查找)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实验3 动态规划(0/1背包)
- 下一篇: 实验1 最小生成树问题【Kruskal+