欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的遞歸算法詳解

 更新時間:2021年09月10日 11:45:57   作者:Craftsman-L  
Java遞歸算法是基于Java語言實現(xiàn)的遞歸算法。遞歸算法對解決一大類問題很有效,它可以使算法簡潔和易于理解。接下來通過本文給大家介紹Java遞歸算法相關知識,感興趣的朋友一起學習吧

一、介紹

1、介紹

遞歸:遞歸就是方法自己調用自己,每次調用時傳入不同的變量。遞歸有助于編程者解決復雜的問題,同時可以讓代碼變得簡潔。

迭代和遞歸區(qū)別:迭代使用的是循環(huán)結構,遞歸使用的選擇結構。使用遞歸能使程序的結構更清晰、更簡潔、更容易讓人理解,從而減少讀懂代碼的時間。其時間復雜度就是遞歸的次數(shù)。

但大量的遞歸調用會建立函數(shù)的副本,會消耗大量的時間和內存,而迭代則不需要此種付出。

遞歸函數(shù)分為調用和回退階段,遞歸的回退順序是它調用順序的逆序。

分治:當一個問題規(guī)模較大且不易求解的時候,就可以考慮將問題分成幾個小的模塊,逐一解決。

2、案例

  • 兔子繁殖的問題。(斐波那契數(shù)列)。
  • 計算 n! 。
  • 任意長度的字符串反向輸出。
  • 折半查找算法的遞歸實現(xiàn)。
  • 漢諾塔問題
  • 八皇后問題

二、迷宮問題

問題:尋找一條從起始點到達終點的有效路徑。

代碼示例:迷宮

public class MiGong {
    /**
     * 0:該點沒有走過, 1:表示墻, 2:可以走, 3:該點已經走過,但是走不通\
     * 策略: 下->右->上->左, 如果該點走不通,再回溯
     */
    private int[][] map;
    private int desX;
    private int desY;
    /**
     * 構建 row*col的迷宮
     *
     * @param row 行
     * @param col 列
     */
    public MiGong(int row, int col) {
        if (row <= 0 || col <= 0) {
            return;
        }
        map = new int[row][col];
        // 默認 上下左右 全部為墻
        for (int i = 0; i < col; i++) {
            map[0][i] = 1;
            map[row - 1][i] = 1;
        }
        for (int i = 0; i < row; i++) {
            map[i][0] = 1;
            map[i][col - 1] = 1;
        }
    }
    /**
     * 在迷宮內部添加擋板
     *
     * @param i 橫坐標
     * @param j 縱坐標
     */
    public void addBaffle(int i, int j) {
        if (map == null) {
            return;
        }
        // 外面一周都是墻
        if (i > 0 && i < map.length - 1 && j > 0 && j < map[0].length - 1) {
            map[i][j] = 1;
        }
    }
    /**
     * 設置迷宮的終點位置
     *
     * @param desX 橫坐標
     * @param desY 縱坐標
     */
    public void setDes(int desX, int desY) {
        this.desX = desX;
        this.desY = desY;
    }
    public boolean setWay(int i, int j) {
        // 通路已經找到
        if (map[desX][desY] == 2) {
            return true;
        } else {
            if (map[i][j] != 0) {
                return false;
            }
            // map[i][j] == 0 按照策略 下->右->上->左 遞歸
            // 假定該點是可以走通.
            map[i][j] = 2;
            if (setWay(i + 1, j)) {
                return true;
            } else if (setWay(i, j + 1)) {
                return true;
            } else if (setWay(i - 1, j)) {
                return true;
            } else if (setWay(i, j - 1)) {
                return true;
            } else {
                // 說明該點是走不通,是死路
                map[i][j] = 3;
                return false;
            }
        }
    }
    // 顯示地圖
    public void show() {
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }
}

  代碼示例:測試類

// 測試類
public class Main {
    public static void main(String[] args) {
        MiGong miGong = new MiGong(8, 7);
        miGong.addBaffle(3, 1);
        miGong.addBaffle(3, 2);
        miGong.setDes(6, 5); // 設置目的地
        System.out.println("初始地圖的情況");
        miGong.show();
        miGong.setWay(1, 1); // 設置起始位置
        System.out.println("小球走過的路徑,地圖的情況");
        miGong.show();
    }
}

// 結果
初始地圖的情況
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
小球走過的路徑,地圖的情況
1 1 1 1 1 1 1
1 2 0 0 0 0 1
1 2 2 2 0 0 1
1 1 1 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 2 2 1
1 1 1 1 1 1 1

三、八皇后問題

問題:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即:任意兩個皇后都不能處于同一行、同一列或同一斜線上,問有多少種擺法。

代碼示例:八皇后

public class Queue8 {
    private static final int MAX = 8;
    // 保存皇后放置的位置,比如 arr = {0, 4, 7, 5, 2, 6, 1, 3}
    private final int[] array = new int[MAX];
    public static int count = 0;
    public static int judgeCount = 0;
    public void check() {
        this.check(0);
    }
    // check 是每一次遞歸時,進入到check中都有 for(int i = 0; i < max; i++),因此會有回溯
    private void check(int n) {
        // n = 8, 表示8個皇后就已經放好
        if (n == MAX) {
            print();
            return;
        }
        for (int i = 0; i < MAX; i++) {
            array[n] = i;

            // 判斷當放置第n個皇后到i列時,是否沖突
            // 不沖突
            if (!judge(n)) {
                // 接著放n+1個皇后,即開始遞歸
                check(n + 1);
            }
        }
    }
    private boolean judge(int n) {
        judgeCount++;
        for (int i = 0; i < n; i++) {
            // 同一列 或 同一斜線
            if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
                return true;
            }
        }
        return false;
    }
    private void print() {
        count++;
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

}

代碼示例:測試類

// 測試類
public class Main {
    public static void main(String[] args) {
        Queue8 queue8 = new Queue8();
        queue8.check();
        System.out.printf("一共有%d解法", Queue8.count);
        System.out.printf("一共判斷沖突的次數(shù)%d次", Queue8.judgeCount); // 1.5w
    }
}

四、漢諾塔問題

1、問題

2、思想

如果 n = 1,A -> C

如果 n >= 2,總是看做是兩個盤,①最下邊的盤。②上面所有的盤。則,步驟:

(1)先把上面所有的盤 A->B

(2)把最下邊的盤 A->C

(3)把 B 塔的所有盤 從 B->C

3、代碼

代碼示例:漢諾塔問題

// 漢諾塔
public class Hanoitower {
    // 使用分治算法
    public static void move(int num, char a, char b, char c) {
        // 如果只有一個盤
        if (num == 1) {
            System.out.println("第1個盤從 " + a + "->" + c);
        } else {
            // n >= 2,總是看做是兩個盤,①最下邊的盤。②上面所有的盤。則,步驟:
            // 1.先把上面所有的盤 A->B.移動過程會使用到 c
            move(num - 1, a, c, b);
            // 2.把最下邊的盤 A->C
            System.out.println("第" + num + "個盤從 " + a + "->" + c);
            // 3.把 B 塔的所有盤 從 B->C.移動過程會使用到 a
            move(num - 1, b, a, c);
        }
    }
}

代碼示例:測試類

// 測試類
public class Main {
    public static void main(String[] args) {
        Hanoitower.move(3, 'A', 'B', 'C');
    }
}

// 結果
第1個盤從 A->C
第2個盤從 A->B
第1個盤從 C->B
第3個盤從 A->C
第1個盤從 B->A
第2個盤從 B->C
第1個盤從 A->C

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!

相關文章

  • Java中的IO流原理和流的分類詳解

    Java中的IO流原理和流的分類詳解

    這篇文章主要介紹了Java中的IO流原理和流的分類詳解,Java?io流是Java編程語言中用于輸入和輸出操作的一種機制。它提供了一組類和接口,用于處理不同類型的數(shù)據(jù)流,包括文件、網(wǎng)絡連接、內存等,需要的朋友可以參考下
    2023-10-10
  • Java線程阻塞和喚醒的幾種方式詳解

    Java線程阻塞和喚醒的幾種方式詳解

    這篇文章主要介紹了Java線程阻塞和喚醒的幾種方式詳解,線程阻塞是指當一個線程無法繼續(xù)執(zhí)行時,它會進入阻塞狀態(tài),直到某個條件滿足后才能繼續(xù)執(zhí)行,線程阻塞可以通過多種方式實現(xiàn),如等待鎖、等待IO操作、等待其他線程的完成等,需要的朋友可以參考下
    2023-10-10
  • 詳解如何使用Java流API構建樹形結構數(shù)據(jù)

    詳解如何使用Java流API構建樹形結構數(shù)據(jù)

    在實際開發(fā)中,構建樹狀層次結構是常見需求,本文主要為大家詳細介紹了如何使用Java 8 Stream API將扁平化的菜單數(shù)據(jù)轉換為具有層級關系的樹形結構,需要的可以參考下
    2024-04-04
  • 使用Mybatis更新時候只更新變更部分的方法

    使用Mybatis更新時候只更新變更部分的方法

    這篇文章主要介紹了使用Mybatis更新時候只更新變更部分的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring Boot中如何使用Convert接口實現(xiàn)類型轉換器

    Spring Boot中如何使用Convert接口實現(xiàn)類型轉換器

    這篇文章主要介紹了Spring Boot中使用Convert接口實現(xiàn)類型轉換器的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java Swing 非常漂亮外觀Nimbus的使用方法實例

    Java Swing 非常漂亮外觀Nimbus的使用方法實例

    Java Swing 非常漂亮外觀Nimbus的使用方法實例,需要的朋友可以參考一下
    2013-02-02
  • Java面向對象基礎之多態(tài)性,抽象類和接口

    Java面向對象基礎之多態(tài)性,抽象類和接口

    這篇文章主要介紹了Java面向對象基礎:多態(tài)性,抽象類和接口,文中代碼可以幫助各位更好的理解學習,有需求的小伙伴可以參考下
    2020-05-05
  • Java實現(xiàn)簡易生產者消費者模型過程解析

    Java實現(xiàn)簡易生產者消費者模型過程解析

    這篇文章主要介紹了Java實現(xiàn)簡易生產者消費者模型過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Java中實現(xiàn)獲取路徑的方法匯總

    Java中實現(xiàn)獲取路徑的方法匯總

    本文給大家匯總分享的是Java中實現(xiàn)獲取路徑的方法,非常的簡單實用,需要的小伙伴可以參考下。
    2015-03-03
  • SpringBoot實戰(zhàn)之處理異常案例詳解

    SpringBoot實戰(zhàn)之處理異常案例詳解

    這篇文章主要介紹了SpringBoot實戰(zhàn)之處理異常案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09

最新評論