Algorithm Practice Record【5】

「数字三角形最大和A一递归」

题目描述
在下面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。
只需要求出这个最大和即可,不必给出具体路径。 三角形的行数大于1小于等于100,数字为 0 - 99
输入格式:
5 //表示三角形的行数 接下来输入三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
要求输出最大和
代码案例解析

import java.util.Arrays;
import java.util.Scanner;

public class 数字三角形最大和A一递归 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        int n = input.nextInt() ;
        int [][] arr = new int [n][] ;
        for(int i=0; i<n; i++){ //为二维数组分配空间
            arr[i] = new int[i+1] ;
        }
        for(int i=0; i<n; i++){
            for(int j=0; j<i+1; j++){
                arr[i][j] = input.nextInt() ;
            }
        }
        // 打印二维数组
        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.toString(arr[i]));
        }
        // 进行递归计算
        System.out.println(max1(arr,0,0));
    }

    public static int max1(int [][] arr, int i, int j){
        int rowIndex = arr.length ;
        if(i == rowIndex - 1){
            return arr[i][j] ;
        } else{ //当前数字+max(左下路径,右下路径)
            return arr[i][j] + Math.max(max1(arr,i+1, j), max1(arr, i+1, j+1)) ;
        }
    }
}

「数字三角形最大和B之一维数组动规逆推」

代码案例解析

import java.util.Scanner;

public class 数字三角形最大和B一一维动规逆推 {
    public static void main(String[] args) {
        // 初始化输入的二维数组
        Scanner in = new Scanner(System.in);
        int rowSize = in.nextInt();
        int[][] arr = new int[rowSize][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[i+1];
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < i + 1; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        diTuiArr(arr);

    }

    /**
     * 从下而上递推解法
     * @param arr
     */
    static void diTuiArr(int[][] arr){
        // 定义存储的一维数组
        int[] newArr = new int[arr[arr.length-1].length];
        for (int i = 0; i < newArr.length; i++) {
            newArr[i] = arr[arr.length-1][i];
        }
        // 从倒数第二行开始逆推
        for (int i = arr.length-2; i >=0; i--) {
            for (int j = 0; j <= i; j++) {
                newArr[j] = Math.max(newArr[j],newArr[j+1])+arr[i][j];
            }
        }
        System.out.println(newArr[0]);
    }
}

「数字三角形最大和C之一维数组递归规划」

代码案例解析

import java.util.Arrays;
import java.util.Scanner;

public class 数字三角形最大和C一一维递归规划 {
    static int arr[][];
    static int newArr[][];
    public static void main(String[] args) {
        // 初始化输入的二维数组
        Scanner in = new Scanner(System.in);
        int rowSize = in.nextInt();
        arr = new int[rowSize][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[i+1];
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < i + 1; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        int colSize = arr[rowSize-1].length;
        // 新建一个同大小数组
        newArr = new int[rowSize][colSize];
        for (int i = 0; i < newArr.length; i++) {
            for (int j = 0; j < newArr[i].length; j++) {
                newArr[i][j] = -1;
            }
        }
        System.out.println(diGuiArr(0,0));
    }

    static int diGuiArr(int n,int m){
        if( newArr[n][m] != -1 ) {
            return newArr[n][m];
        }
        if(n==arr.length-1){
            newArr[n][m] = arr[n][m];
        } else{
            int x = diGuiArr(n+1,m);
            int y = diGuiArr(n+1,m+1);
            newArr[n][m] = Math.max(x,y)+ arr[n][m];
        }
        return newArr[n][m];
    }
    static void printArr(int[][] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.toString(arr[i]));
        }
    }
}

「数字三角形最大和D之二维动规顺推」

代码案例解析

import java.util.Scanner;

public class 数字三角形最大和D一二维动规顺推 {
    /**
     * 题目描述
     * 在下面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。
     * 只需要求出这个最大和即可,不必给出具体路径。 三角形的行数大于1小于等于100,数字为 0 - 99
     *
     *     输入格式:
     *
     *     5      //表示三角形的行数    接下来输入三角形
     *
     *     7                              7
     *     3   8                        3   8
     *     8   1   0                  8   1   0
     *     2   7   4   4            2   7   4   4
     *     4   5   2   6   5      4   5   2   6   5
     *
     *     要求输出最大和
     * @param args
     */
    public static void main(String[] args) {
        // 初始化输入的二维数组
        Scanner in = new Scanner(System.in);
        int rowSize = in.nextInt();
        int[][] arr = new int[rowSize][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[i+1];
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < i + 1; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        // 初始化最左边
        for (int i = 1; i < rowSize; i++) {
            arr[i][0] = arr[i][0] + arr[i-1][0];
        }
        // 初始化最右边
        for (int i = 1; i < rowSize; i++) {
            arr[i][i] = arr[i][i] + arr[i-1][i-1];
        }
        PrintArrsTwoUtils.printArr(arr);

        // 循环往下最大值[i][j] = max([i][j-1],[i-1][j-1])
        for (int i = 2; i < rowSize; i++) {
            for (int j = 1; j < i; j++) {
                arr[i][j] = Math.max(arr[i-1][j],arr[i-1][j-1])+arr[i][j];
                PrintArrsTwoUtils.printArr(arr);
            }
        }

        int max = Integer.MIN_VALUE;
        for (int i = 0; i < rowSize; i++) {
            max = Math.max(arr[rowSize-1][i],max);
        }
        System.out.println(max);
    }

//                    [7]
//                  [10, 15]
//                [18,  16,  15]
//              [20,  25,   20,  19]
//            [24,  30,   27,   26, 24]
}

「整数拆分A一递归」

题目描述
给定一个正整数,我们可以定义出下面的公式:
N=a[1]+a[2]+a[3]+…+a[m];
a[i]>0,1<=m<=N;
对于一个正整数,求解满足上面公式的所有算式组合,如,对于整数 4 :
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
所以上面的结果是 5 。
注意:对于 “4 = 3 + 1” 和 “4 = 1 + 3” ,这两处算式实际上是同一个组合!
样例
输入样例
4
10
20
输出样例
5
42
627
代码案例解析

import java.util.Scanner;

public class 整数拆分A一递归 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        System.out.println(method(num,num));
    }

    /**
     * 数字n的m划分
     * @param n 需要划分的数字
     * @param max 划分最大数
     * @return
     */
    static int method(int n, int max) {
        if(n == 1 || max == 1) {
            return 1;
        }
        if(n < max) {
            return method(n, n);
        }
        if(n == max) {
            return 1 + method(n, n - 1);
        } else {
            return method(n - max, max) + method(n, max - 1);
        }
    }
}

「整数拆分B一动态数组」

代码案例解析

import java.util.Scanner;

public class 整数拆分B一动态数组 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()){
            int num = in.nextInt();
            System.out.println(method(num,num));
        }
    }
    static long method(int n, int k){
        long[][] dp = new long[n+1][k+1];
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=k;j++) {
                if(i==1||j==1){
                    dp[i][j]=1;
                } else if(i==j){
                    dp[i][j]=1+dp[i][j-1];
                } else if(i<j) {
                    dp[i][j]=dp[i][i];
                } else if(i>j){
                    dp[i][j]=dp[i-j][j]+dp[i][j-1];
                }
            }
        }
        return dp[n][k];
    }
}

「整数拆分C之一维数组解法」

代码案例解析

import java.util.Scanner;

public class 整数拆分C一一维数组解法 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()){
            int num = in.nextInt();
            System.out.println(combinationCount(num));
        }
    }

    public static int combinationCount(int N) {
        int[] dp = new int[N + 1];
        for (int i = 0; i <= N; i++) {
            dp[i] = 1; // 初始化,每个数自身是一种组合方式
        }
        for (int i = 2; i <= N; i++) {
            for (int j = i; j <= N; j++) {
                dp[j] = dp[j] + dp[j - i]; // 核心动态规划逻辑,j可以由j-i加上i组合得到,所以dp[j] += dp[j-i]
            }
        }
        return dp[N];
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值