八大算法思想


八大算法思想分別是:枚舉、遞推、遞歸、分治、貪心、試探法、動態迭代和模擬算法思想。

1、比較“笨”的枚舉算法思想

    枚舉最大的缺點是運算量比較大,解題效率不高。

如果題目的規模不是很大,在規定的時間與空間限制內能夠求出解,那么最好是采用枚舉法,而無須太在意是夠還有更快的算法,這樣可以使你有更多的時間去解答其他難題。

//枚舉法解決“填寫運算符”的問題
import java.util.Scanner;

public class meijujisuan5ge5 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int j;
        int[] i=new int[5];  //用數組i來表示4個運算符 (5個數之間有四個符號,分別遍歷出所有的情況)
        int sign;//累加運算時的符號
        int count=0;//計數器,統計符合條件的方案
        int num[]=new int[6];//保存操作數(輸入值)
        float left,right;
        char[] oper={' ','+','-','*','/'};
        System.out.println("請輸入5個數,之間用空格隔開:");
        Scanner in=new Scanner(System.in);
        for(j=1;j<=5;j++){
            num[j]=(int)in.nextInt();
        }
        System.out.println("請輸入結果:");
        int result=(int)in.nextInt();
        for(i[1]=1;i[1]<=4;i[1]++){//循環4中運算符,1表示+,2表示-,3表示*,4表示/
            if(i[1]<4||num[2]!=0){//運算符若是、,則第二個運算數不能是0
                for(i[2]=1;i[2]<=4;i[2]++){
                    if(i[2]<4||num[3]!=0){
                        for(i[3]=1;i[3]<=4;i[3]++){
                            if(i[3]<4||num[4]!=0){
                                for(i[4]=1;i[4]<=4;i[4]++){
                                    if(i[4]<4||num[5]!=0){
                                        left=0;
                                        right=num[1];
                                        sign=1;
                                        for(j=1;j<=4;j++){
                                            switch(oper[i[j]]){
                                                case'+':
                                                    left=left+sign*right;
                                                    sign=1;
                                                    right=num[j+1];
                                                    break;
                                                case'-':
                                                    left=left+sign*right;
                                                    sign=-1;
                                                    right=num[j+1];
                                                    break;
                                                case'*':
                                                    right=right*num[j+1];
                                                    break;
                                                case'/':
                                                    right=right/num[j+1];
                                                    break;
                                            }
                                        }
                                        if(left+sign*right==result){
                                            count++;
                                            System.out.print(count+": ");
                                            for(j=1;j<=4;j++){
                                                System.out.print(num[j]);
                                                System.out.print(oper[i[j]]);
                                            }
                                            System.out.println(num[5]+"="+result);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
枚舉算法舉例代碼

2、聰明一點的遞推算法思想

(1)順推法:從已知條件出發,逐步推算出要解決問題的方法

//用順推法解決“斐波那契數列”問題
public class shuntuirabbit {
    public static void main(String[] args){
        int a[]=new int[24];//定義一個存放24個月的數組
        a[0]=a[1]=1;
        for(int i=0;i<24;i++){
            if(i==0||i==1)
            System.out.println("第"+(i+1)+"個月兔子的數量為"+1+"對");
            else{
                a[i]=a[i-1]+a[i-2];
                System.out.println("第"+(i+1)+"個月兔子的數量為"+a[i]+"對");
            }
        }
    }
}
用順推法解決“斐波那契數列”問題

(2)逆推法:從已知結果出發,用迭代表達式逐步推算出問題開始的條件。

/*逆推法解決“銀行存款”問題
母親為兒子小Sun的4年大學學費准備了一筆存款,
銀行年利息為1.71%
*/
public class nituiYinhangcunkuan {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        double fetch=1000;
        double corpus[]=new double[49];
        corpus[48]=fetch;
        int i;
        for(i=47;i>0;i--){
            corpus[i]=(int) (corpus[i+1]+fetch)/(1+0.0171/12);
        }
        for(i=48;i>0;i--)
            System.out.println("第"+i+"個月末本利共計:"+corpus[i]);
    }
}
逆推法解決“銀行存款”問題

3、充分利用自己的遞歸算法思想

使用遞歸算法時,應注意以下幾點:

(1)遞歸時在過程或函數中調用自身的過程。

(2)在使用遞歸策略時,必須有一個明確的遞歸結束條件,這稱為遞歸出口。

(3)遞歸算法通常顯得很簡潔,但是運行效率較低,所以一般不提倡使用遞歸算法設計程序。

(4)在遞歸調用過程中,系統用棧來存儲每一層的返回點和局部量。如果遞歸次數過多,則容易造成棧溢出,所以一般不提倡用遞歸算法設計程序。

【遞推和遞歸的差異】

遞推多想是多米諾骨牌,根據前面幾個得到后面的;

遞歸是大事化小,比如漢諾塔(Hanoi)問題,就是典型的遞歸。

如果一個問題的求解既可以用遞歸算法求解,也可以用遞推算法求解,此時往往選擇遞推算法,因為遞推的效率比遞歸高。

import java.util.Scanner;

//遞歸解決階乘問題(factorial)
public class diguijiechengwenti {
    public static void main(String[] args){
        System.out.println("請輸入要計算階乘的一個整數:");
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        factorial(n);
        System.out.println(n+"的階乘結果為:"+factorial(n));
    }
    private static int factorial(int i) {
        // TODO Auto-generated method stub
        if(i==1){
            return 1;
        }
        else{
            return i*factorial(i-1);
        }
    }
}
遞歸解決階乘問題
/*遞歸解決漢諾塔問題
思路,64個盤從第一個柱子移到第三個柱子,則需要考慮將63個柱子
移到第二個柱子,然后將第64個盤子移到第三根柱子,最后將63個柱子
移到第三個柱子即可
*/
import java.util.Scanner;

public class diguiHannuota {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int h;
        System.out.println("請輸入盤子個數:");
        Scanner in=new Scanner(System.in);
        h=in.nextInt();
        System.out.println("移動"+h+"個盤子的步驟如下:");
        move(h,'a','b','c');
    }

    private static void move(int n, char x, char y, char z) {
        // TODO Auto-generated method stub
        if(n==1){
            System.out.println(x+"-->"+z);
        }
        else{
            move(n-1,x,z,y);//將n-1個盤從x移到y,借助z
            System.out.println(x+"-->"+z);
            move(n-1,y,x,z);
            System.out.println();
        }
    }
}
遞歸解決漢諾塔問題

   

4、各個擊破的分治算法思想

先把各個問題分解成幾個較小的子問題,找到求出這幾個子問題的解法后,再找到合適的方法,把他們組合成求整個大問題的解法。如果這些子問題還是比較大,還可以繼續再把它們分成幾個更小的小子問題,依次類推,直至可以直接求出解為止。這就是分治策略的基本思想。

使用分治算法解題的一般步驟:

(1)分解:將要解決的問題划分成若干個規模較小的同類問題;

(2)求解:當子問題划分得足夠小時,用較簡單的方法解決;

(3)合並:按原問題的要求,將子問題的解逐層合並構成原問題的解。

1)【!!!!】分治算法解決“大數相乘問題”用Java實現?!未完成

2)歐洲冠軍杯比賽日程安排:n個對參賽,比賽n-1天,每個隊都要比而且只能比一次,隊伍的總數為2^n,請你安排比賽。Java實現?!未完成

分析:參賽隊伍比較多時,降低隊伍的規模,直到能夠直接進行求解為止,這樣使用了分治的思想,同時又有遞歸的調用。

當為2個隊的時候,直接賦值,大於2個隊的時候,再進行細分,先確定左上角和右上角,然后再確定左下角和右下角!

分治法能解決的問題一般具有以下4個特征:

(1)當問題的規模縮小到一定的程度就可以容易地解決,此特征是絕大多數問題都可以滿足的,因為問題的計算復雜性一般是隨着問題規模的增加而增加的。

(2)問題可以分解為若干個規模較小的問題,即該問題具有最優子結構性質。此特征是應用分治法的前提。它也是大多數問題可以滿足的,此特征反應了遞歸思想的應用。

(3)(關鍵)利用該問題分解出的子問題的解可以合並為該問題的解;

(4)各個子問題是相互獨立的,即子問題之間不包含公共的子問題。

5、貪心算法思想並不貪婪(追求最優求解,但不一定是能找到最優解)

貪心算法的3個問題:

(1)不能保證最后的解是最優的;

(2)不能用來求最大或最小解問題;

(3)只能求滿足某些約束條件的可行解的范圍。

貪心算法的思路:

(1)建立數學模型來描述問題;

(2)把求解的問題分成若干個子問題;

(3)對每一個子問題進行求解,得到子問題的局部最優解;

(4)把子問題局部最優解合並成為原來問題的解。

彈性算法的基本過程:

(1)從問題的某一個初始解出發;

(2)While能向給定總目標前進一步;

(3)求出可行解的一個解元素;

(4)由所有解元素組成問題的一個可行解。

貪心算法解決裝箱問題,java實現未解決

貪心算法解決找零方案問題,java實現未解決

6、試探法算法思想是一種委婉的做法(也叫回溯法)

試探法解題的基本步驟:

(1)針對所給定問題,定義問題的解空間;

(2)確定易於搜索的解空間結構;

(3)以深度優先方式搜索解空間,並在搜索過程中用剪枝函數避免無效搜索。

試探算法解決“八皇后”問題java實現  未解決

試探算法解決“297彩票組合”問題java實現  未解決

試探法3個要素:

(1)解空間

(2)約束條件

(3)狀態樹

7、迭代算法(輾轉法)

精確迭代

近似迭代:二分法和牛頓迭代法

用迭代算法解決問題時,需要做好3個方面的工作

(1)確定迭代變量:至少存在一個迭代變量

(2)建立迭代關系式:即如何從變量的前一個值推出其下一個值的關系或公式

(3)對迭代過程進行控制:迭代次數和地帶結束條件

使用迭代算法解決“求平方根”問題  java實現

8、模擬算法思想

使用模擬算法解決“猜數字游戲”問題 java實現

使用模擬算法解決“擲骰子游戲”問題 java實現

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM