递归与分治经典案例-Java实现

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与分治经典案例-Java实现相关的知识,希望对你有一定的参考价值。

1-阶乘问题

import java.util.Scanner;

public class Factorial {
    public static int factorial(int n){
        if(n == 0){
            return 1 ;
        }
        return n * factorial(n-1) ;
    }
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        int n = input.nextInt() ;
        System.out.println(factorial(n));
    }
}

2-斐波那契数列

import java.util.Scanner;

public class Fibonacci {
    public static int fibonacci(int n){
        if(n == 1 || n == 2){
            return 1 ;
        }
        return fibonacci(n-1) + fibonacci(n-2) ;
    }
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        int n = input.nextInt() ;
        System.out.println(fibonacci(n));
    }
}

3-汉诺塔


public class HanoiTower {
    public static void hanoiTower(int n, String from, String to, String helper){
        if(n == 1){ //当就一个盘子,则直接从A移动到B,同时退出递归
            System.out.println("将第" + n + "个盘子从" + from + "移动到" + to );
            return ;
        }
        hanoiTower(n-1, from, helper, to) ; //将n-1个盘子从A移动到C,B作为辅助
        System.out.println("将第" + n + "个盘子从" + from + "移动到" + to); //将第n个盘子从A移动到B
        hanoiTower(n-1, helper, to, from) ; //将n-1个盘子从C移动到B
    }
    public static void main(String[] args) {
        hanoiTower(3, "A", "B", "C") ;
    }
}

4-全排列

import java.util.Scanner;

public class FullPermutation {
    public static int count = 0 ;
    public static int f(int n){
        if(n == 0){
            return 1 ;
        }
        return n * f(n-1) ;
    }
    public static void fullPermutation(String prefix, char [] arr){
        if(prefix.length() == arr.length){
            System.out.println(prefix);
            count ++ ;
            if(count == f(arr.length)){ //count等于全排列的个数,则结束递归
                System.exit(0);
            }
        }
        for(int i=0; i<arr.length; i++){
            char c = arr[i] ;
            if(sum(prefix.toCharArray(), c) < sum(arr, c)) {//解决重复问题
                fullPermutation(prefix + c, arr); //将当前字符串作为前缀继续递归下去
            }
        }
    }
    public static int sum(char [] arr, char c){
        int count1 = 0 ;
        for(int i=0; i<arr.length; i++){
            if(arr[i] == c){
                count1 ++ ;
            }
        }
        return count1 ;
    }
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        String s = input.next() ;
        fullPermutation("", s.toCharArray()) ;
    }
}

5-二分查找

public class BinarySearch2 {
    public static int binarySearch(int [] arr, int key, int low, int high){
        int mid = (low + high) >>> 1 ;
        if(low > high){
            return -1 ;
        }
        if(arr[mid] > key){
            return binarySearch(arr, key, low, high-1) ;
        }else if(arr[mid] < key){
            return binarySearch(arr, key, low+1, high) ;
        }else{
            return mid ;
        }
    }
    public static void main(String[] args) {
        int [] arr = new int []{1,3,5,6,8,9,10, 12, 28,50, 100} ;
        System.out.println(binarySearch(arr, 10, 0, arr.length - 1));
        System.out.println(binarySearch(arr, 7, 0, arr.length - 1));
    }
}

6-棋盘覆盖

import java.util.Scanner;

/**
 * 棋盘覆盖问题
 * 在一个2的k次方 x 2的k次方个方格组成的棋盘中
 * 恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,
 * 要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
 * Input
 * k,dr,dc。k定义如前,dr,dc分别表示特殊方格所在的行号和列号 1= < k < =6
 *
 * Output
 * 按照左上,右上,左下,右下的顺序用分治法求解。特殊方格标0,其他位置按上述顺序依次标记。
 */
public class ChessBoard {
    public static int [][] board = new int [150][150] ; //不超过64
    public static int tile = 0 ;
    public static void chessBoard(int tr, int tc, int dr, int dc, int size){
        if(size == 1){ //仅一个点,直接返回
            return ;
        }
        int t = ++tile ; //L型骨牌编号
        int s = size / 2 ;
        //覆盖左上角的棋盘
        if(tr+s>dr && tc+s>dc){ //特殊方格在左上角区域中
            chessBoard(tr, tc, dr, dc, s) ;
        }else{
            //特殊方格不在左上角棋盘中,将特殊值填到右下角
            board[tr+s-1][tc+s-1] = t ;
            chessBoard(tr, tc, tr+s-1, tc+s-1, s) ;
        }
        //覆盖右上角的棋盘
        if(tr+s>dr && tc+s<=dc){ //特殊方格在右上角区域
            chessBoard(tr, tc+s, dr, dc, s) ;
        }else{
            board[tr+s-1][tc+s] = t ;
            chessBoard(tr, tc+s, tr+s-1, tc+s, s) ;
        }
        //覆盖左下角的棋盘
        if(tr+s<=dr && tc+s>dc){ //特殊方格在左下角区域
            chessBoard(tr+s, tc, dr, dc, s) ;
        }else{
            board[tr+s][tc+s-1] = t ;
            chessBoard(tr+s, tc, tr+s, tc+s-1, s) ;
        }
        //覆盖右下角
        if(tr+s<=dr && tc+s <= dc){
            chessBoard(tr+s, tc+s, dr, dc, s) ;
        }else{
            board[tr+s][tc+s]=t;
            chessBoard(tr+s,tc+s,tr+s,tc+s,s);
        }
    }
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        int k = input.nextInt() ;
        int dr = input.nextInt() ; //特殊方格的行号
        int dc = input.nextInt() ; //特殊方格的列号
        int size = (int)Math.pow(2, k) ;
        chessBoard(0, 0, dr, dc, size);
        for(int i=0; i<size; i++){
            for(int j=0; j<size; j++){
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }
}

7-归并排序

public class MergeSort {
    public static void mergeSort(int [] arr, int p,int r){
        if(p < r){
            int mid = (p + r) >>> 1 ;
            mergeSort(arr, p, mid -1) ; //左侧归并排序
            mergeSort(arr, mid+1, r) ; //右侧归并排序
            merge(arr, p, r, mid) ; //合并
        }
    }
    public static void merge(int [] arr, int p, int r, int mid){ //归并排序的重点在于归并
        int [] helper = new int [arr.length] ;
        for(int i=0; i<arr.length; i++){
            helper[i] = arr[i] ;
        }
        int left = p ;
        int right = mid + 1 ;
        int current = p ;
        while(left <= mid && right <=r){
            if(helper[left] > helper[right]){
                arr[current++] = helper[right++] ;
            }else{
                arr[current++] = helper[left++] ;
            }
        }
        while(left <= mid){
            arr[current++] = helper[left++] ;
        }
        while(right <= r){
            arr[current++] = helper[right++] ;
        }
    }
    public static void main(String[] args) {
        int [] arr = new int [] {2,1,3,7,6,4,9,8,0} ;
        mergeSort(arr, 0, arr.length-1);
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i] + " ");
        }
    }
}

8-快速排序

public class QuickSort {
    public static void swap(int [] arr, int left, int right){
        int temp = arr[left] ;
        arr[left] = arr[right] ;
        arr[right] = temp ;
    }
    public static int partition(int [] arr, int left, int right){
        int pivot = arr[left] ; //初始化主元
        int left1 = left + 1 ;
        int right1 = right ;
        while(left1 <= right1){
            while(left1 <= right1 && arr[left1] <= pivot){
                left1 ++ ;
            }
            while(left1 <= right1 && arr[right1] >= pivot){
                right1 -- ;
            }
            if(left1 < right1) {
                swap(arr, left1, right1);
            }
        }
        swap(arr, left, right1) ;
        return right1 ;
    }
    public static void quickSort(int [] arr, int left, int right){//先划分,再递归进行快速排序,重点在划分上
        if(left < right){
            int q = partition(arr, left, right) ;
            quickSort(arr, left, q-1) ;
            quickSort(arr, q+1, right) ;
        }
    }
    public static void main(String[] args) {
        int [] arr = new int [] {2,15,3,7,9,4,0递归思想

五大经典算法思想之分治策略

算法浅谈——分治算法与归并快速排序(附代码和动图演示)

经典分治 - 汉诺塔游戏

算法漫游指北(第十篇):泛型递归递归代码模板递归思维要点分治算法回溯算法

经典算法之快速排序