小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

編程5大算法總結(jié)

 長沙7喜 2018-12-10

一、基本概念

在計(jì)算機(jī)科學(xué)中,分治法是一種很重要的算法。字面上的解釋是“分而治之”,就是把一個(gè)復(fù)雜的問題分成兩個(gè)或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最后子問題可以簡單的直接求解,原問題的解即子問題的解的合并。這個(gè)技巧是很多高效算法的基礎(chǔ),如排序算法(快速排序,歸并排序),傅立葉變換(快速傅立葉變換)……

任何一個(gè)可以用計(jì)算機(jī)求解的問題所需的計(jì)算時(shí)間都與其規(guī)模有關(guān)。問題的規(guī)模越小,越容易直接求解,解題所需的計(jì)算時(shí)間也越少。例如,對于n個(gè)元素的排序問題,當(dāng)n=1時(shí),不需任何計(jì)算。n=2時(shí),只要作一次比較即可排好序。n=3時(shí)只要作3次比較即可,…。而當(dāng)n較大時(shí),問題就不那么容易處理了。要想直接解決一個(gè)規(guī)模較大的問題,有時(shí)是相當(dāng)困難的。 具體可以:

分解(Divide):將原問題分解成一系列子問題;
解決(conquer):遞歸地解各個(gè)子問題。若子問題足夠小,則直接求解;
合并(Combine):將子問題的結(jié)果合并成原問題的解。
合并排序(merge sort)是一個(gè)典型分治法的例子。其對應(yīng)的直觀的操作如下:


分解:將n個(gè)元素分成各含n/2個(gè)元素的子序列;
解決:用合并排序法對兩個(gè)子序列遞歸地排序;
合并:合并兩個(gè)已排序的子序列以得到排序結(jié)果。

二、基本思想及策略

分治法的設(shè)計(jì)思想是:將一個(gè)難以直接解決的大問題,分割成一些規(guī)模較小的相同問題,以便各個(gè)擊破,分而治之。

分治策略是:對于一個(gè)規(guī)模為n的問題,若該問題可以容易地解決(比如說規(guī)模n較?。﹦t直接解決,否則將其分解為k個(gè)規(guī)模較小的子問題,這些子問題互相獨(dú)立且與原問題形式相同,遞歸地解這些子問題,然后將各子問題的解合并得到原問題的解。這種算法設(shè)計(jì)策略叫做分治法。

如果原問題可分割成k個(gè)子問題,1<k≤n,且這些子問題都可解并可利用這些子問題的解求出原問題的解,那么這種分治法就是可行的。由分治法產(chǎn)生的子問題往往是原問題的較小模式,這就為使用遞歸技術(shù)提供了方便。在這種情況下,反復(fù)應(yīng)用分治手段,可以使子問題與原問題類型一致而其規(guī)模卻不斷縮小,最終使子問題縮小到很容易直接求出其解。這自然導(dǎo)致遞歸過程的產(chǎn)生。分治與遞歸像一對孿生兄弟,經(jīng)常同時(shí)應(yīng)用在算法設(shè)計(jì)之中,并由此產(chǎn)生許多高效算法。

三、分治法適用的情況

分治法所能解決的問題一般具有以下幾個(gè)特征:

1) 該問題的規(guī)??s小到一定的程度就可以容易地解決

2) 該問題可以分解為若干個(gè)規(guī)模較小的相同問題,即該問題具有最優(yōu)子結(jié)構(gòu)性質(zhì)。

3) 利用該問題分解出的子問題的解可以合并為該問題的解;

4) 該問題所分解出的各個(gè)子問題是相互獨(dú)立的,即子問題之間不包含公共的子子問題。

第一條特征是絕大多數(shù)問題都可以滿足的,因?yàn)閱栴}的計(jì)算復(fù)雜性一般是隨著問題規(guī)模的增加而增加;

第二條特征是應(yīng)用分治法的前提它也是大多數(shù)問題可以滿足的,此特征反映了遞歸思想的應(yīng)用;、

第三條特征是關(guān)鍵,能否利用分治法完全取決于問題是否具有第三條特征,如果具備了第一條和第二條特征,而不具備第三條特征,則可以考慮用貪心法或動態(tài)規(guī)劃法

第四條特征涉及到分治法的效率,如果各子問題是不獨(dú)立的則分治法要做許多不必要的工作,重復(fù)地解公共的子問題,此時(shí)雖然可用分治法,但一般用動態(tài)規(guī)劃法較好。

四、分治法的基本步驟

分治法在每一層遞歸上都有三個(gè)步驟:

step1 分解:將原問題分解為若干個(gè)規(guī)模較小,相互獨(dú)立,與原問題形式相同的子問題;

step2 解決:若子問題規(guī)模較小而容易被解決則直接解,否則遞歸地解各個(gè)子問題

step3 合并:將各個(gè)子問題的解合并為原問題的解。

它的一般的算法設(shè)計(jì)模式如下:

Divide-and-Conquer(P)

1. if |P|≤n0

2. then return(ADHOC(P))

3. 將P分解為較小的子問題 P1 ,P2 ,...,Pk

4. for i←1 to k

5. do yi ← Divide-and-Conquer(Pi) △ 遞歸解決Pi

6. T ← MERGE(y1,y2,...,yk) △ 合并子問題

7. return(T)

其中|P|表示問題P的規(guī)模;n0為一閾值,表示當(dāng)問題P的規(guī)模不超過n0時(shí),問題已容易直接解出,不必再繼續(xù)分解。ADHOC(P)是該分治法中的基本子算法,用于直接解小規(guī)模的問題P。因此,當(dāng)P的規(guī)模不超過n0時(shí)直接用算法ADHOC(P)求解。算法MERGE(y1,y2,...,yk)是該分治法中的合并子算法,用于將P的子問題P1 ,P2 ,...,Pk的相應(yīng)的解y1,y2,...,yk合并為P的解。

實(shí)例:

 [找出偽幣] 給你一個(gè)裝有1 6個(gè)硬幣的袋子。1 6個(gè)硬幣中有一個(gè)是偽造的,并且那個(gè)偽造的硬幣比真的硬幣要輕一些。你的任務(wù)是找出這個(gè)偽造的硬幣。

為了幫助你完成這一任務(wù),將提供一臺可用來比較兩組硬幣重量的儀器,利用這臺儀器,可以知道兩組硬幣的重量是否相同。比較硬幣1與硬幣2的重量。假如硬幣1比硬幣2輕,則硬幣1是偽造的;假如硬幣2比硬幣1輕,則硬幣2是偽造的。這樣就完成了任務(wù)。假如兩硬幣重量相等,則比較硬幣3和硬幣4。同樣,假如有一個(gè)硬幣輕一些,則尋找偽幣的任務(wù)完成。假如兩硬幣重量相等,則繼續(xù)比較硬幣5和硬幣6。按照這種方式,可以最多通過8次比較來判斷偽幣的存在并找出這一偽幣。 

另外一種方法就是利用分而治之方法。假如把1 6硬幣的例子看成一個(gè)大的問題。第一步,把這一問題分成兩個(gè)小問題。隨機(jī)選擇8個(gè)硬幣作為第一組稱為A組,剩下的8個(gè)硬幣作為第二組稱為B組。這樣,就把1 6個(gè)硬幣的問題分成兩個(gè)8硬幣的問題來解決。第二步,判斷A和B組中是否有偽幣??梢岳脙x器來比較A組硬幣和B組硬幣的重量。假如兩組硬幣重量相等,則可以判斷偽幣不存在。假如兩組硬幣重量不相等,則存在偽幣,并且可以判斷它位于較輕的那一組硬幣中。最后,在第三步中,用第二步的結(jié)果得出原先1 6個(gè)硬幣問題的答案。若僅僅判斷硬幣是否存在,則第三步非常簡單。無論A組還是B組中有偽幣,都可以推斷這1 6個(gè)硬幣中存在偽幣。因此,僅僅通過一次重量的比較,就可以判斷偽幣是否存在。 

現(xiàn)在假設(shè)需要識別出這一偽幣。把兩個(gè)或三個(gè)硬幣的情況作為不可再分的小問題。注意如果只有一個(gè)硬幣,那么不能判斷出它是否就是偽幣。在一個(gè)小問題中,通過將一個(gè)硬幣分別與其他兩個(gè)硬幣比較,最多比較兩次就可以找到偽幣。這樣,1 6硬幣的問題就被分為兩個(gè)8硬幣(A組和B組)的問題。通過比較這兩組硬幣的重量,可以判斷偽幣是否存在。如果沒有偽幣,則算法終止。否則,繼續(xù)劃分這兩組硬幣來尋找偽幣。假設(shè)B是輕的那一組,因此再把它分成兩組,每組有4個(gè)硬幣。稱其中一組為B1,另一組為B2。比較這兩組,肯定有一組輕一些。如果B1輕,則偽幣在B1中,再將B1又分成兩組,每組有兩個(gè)硬幣,稱其中一組為B1a,另一組為B1b。比較這兩組,可以得到一個(gè)較輕的組。由于這個(gè)組只有兩個(gè)硬幣,因此不必再細(xì)分。比較組中兩個(gè)硬幣的重量,可以立即知道哪一個(gè)硬幣輕一些。較輕的硬幣就是所要找的偽幣。

五、分治法的復(fù)雜性分析

一個(gè)分治法將規(guī)模為n的問題分成k個(gè)規(guī)模為n/m的子問題去解。設(shè)分解閥值n0=1,且adhoc解規(guī)模為1的問題耗費(fèi)1個(gè)單位時(shí)間。再設(shè)將原問題分解為k個(gè)子問題以及用merge將k個(gè)子問題的解合并為原問題的解需用f(n)個(gè)單位時(shí)間。用T(n)表示該分治法解規(guī)模為|P|=n的問題所需的計(jì)算時(shí)間,則有:

T(n)= k T(n/m)+f(n)

通過迭代法求得方程的解:

遞歸方程及其解只給出n等于m的方冪時(shí)T(n)的值,但是如果認(rèn)為T(n)足夠平滑,那么由n等于m的方冪時(shí)T(n)的值可以估計(jì)T(n)的增長速度。通常假定T(n)是單調(diào)上升的,從而當(dāng) mi≤n<mi+1時(shí),T(mi)≤T(n)<T(mi+1)。

 

六、可使用分治法求解的一些經(jīng)典問題

(1)二分搜索

(2)大整數(shù)乘法

(3)Strassen矩陣乘法

(4)棋盤覆蓋

(5)合并排序

(6)快速排序

(7)線性時(shí)間選擇

(8)最接近點(diǎn)對問題

(9)循環(huán)賽日程表

(10)漢諾塔

 

七、依據(jù)分治法設(shè)計(jì)程序時(shí)的思維過程

實(shí)際上就是類似于數(shù)學(xué)歸納法,找到解決本問題的求解方程公式,然后根據(jù)方程公式設(shè)計(jì)遞歸程序。

1、一定是先找到最小問題規(guī)模時(shí)的求解方法

2、然后考慮隨著問題規(guī)模增大時(shí)的求解方法

3、找到求解的遞歸函數(shù)式后(各種規(guī)?;蛞蜃樱?,設(shè)計(jì)遞歸程序即可。

應(yīng)用之歸并排序:

  1. package sort;
  2. public class mergerSort2 {
  3. static void merge(int arr[], int L, int M, int R) {//合并算法
  4. int LEFT_SIZE = M - L;//left array size
  5. int RIGHT_SIZE = R - M + 1;
  6. // int left[LEFT_SIZE];
  7. // int right[RIGHT_SIZE];
  8. int left[] = new int[LEFT_SIZE];
  9. int right[] = new int[RIGHT_SIZE];
  10. int i, j, k;
  11. // 1. Fill in the left sub array
  12. for (i=L; i<M; i++) {
  13. left[i-L] = arr[i];//sub array begin from 0
  14. }
  15. // 2. Fill in the right sub array
  16. for (i=M; i<=R; i++) {
  17. right[i-M] = arr[i];//sub array begin from 0
  18. }
  19. // 3. Merge into the original array
  20. i = 0; j = 0; k = L;//k point to the left array
  21. while (i < LEFT_SIZE && j < RIGHT_SIZE) {//沒有到達(dá)子矩陣的頂端,這時(shí)比較左右矩陣如果左面小arr[k]位置放入左面值,即達(dá)到取曉得放入新的矩陣,i,j,k指針各自加上1
  22. if (left[i] < right[j]) {
  23. arr[k] = left[i];
  24. i++;
  25. k++;
  26. }
  27. else {
  28. arr[k] = right[j];
  29. j++;
  30. k++;
  31. }
  32. }
  33. while (i < LEFT_SIZE) {//一邊到達(dá)了頂端,那么如果另一方還沒到直接放入新矩陣
  34. arr[k] = left[i];
  35. i++;
  36. k++;
  37. }
  38. while (j < RIGHT_SIZE) {
  39. arr[k] = right[j];
  40. j++;
  41. k++;
  42. }
  43. }
  44. static void mergeSort(int arr[], int L, int R) {//分治+歸并!?。?!
  45. if (L == R) {//分支的結(jié)束為只有一個(gè)
  46. return;
  47. }
  48. else {
  49. int M = (L + R) / 2;
  50. mergeSort(arr, L, M);
  51. mergeSort(arr, M+1, R);
  52. merge(arr, L, M+1, R);
  53. }
  54. }
  55. public static void main(String[] args)
  56. {
  57. int arr[] = {6, 8, 10, 9, 4, 5, 2, 7,3};
  58. int L = 0;
  59. int R = arr.length;
  60. mergeSort(arr, L, R);
  61. int i;
  62. for (i=0; i<=R; i++) {
  63. System.out.println(arr[i]);
  64. }
  65. }
  66. }


    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多