2.三角形最小路径和,打家劫舍

1.三角形最小路径和

https://leetcode-cn.com/problems/triangle/

     public int minimumTotal(List<List<Integer>> list) {
            // 初始化数组长度为:最低层数组的长度
            int[] A = new int[list.get(list.size() - 1).size() + 1];
            // 最底层开始
            for (int i = list.size() - 1; i >= 0; i--) {
                for (int j = 0; j < list.get(i).size(); j++) {
                    // 第一次循环:初始化最底层,之后逐层向上累加
                    A[j] = Math.min(A[j], A[j + 1]) + list.get(i).get(j);
                }
            }
            return A[0];
     }

2.打家劫舍

https://leetcode-cn.com/problems/house-robber/

单排排列

    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 0 || nums == null) {
            return 0;
        }
        // 每个房屋都可以选择偷或者不偷: 定义二维数组,第二维度表示状态
        int[][] a = new int[n][2];
        // 第一个房屋不偷
        a[0][0] = 0;
        // 第一个房屋偷
        a[0][1] = nums[0];
        for (int i = 1; i < n; i++) {
            // 状态迭代,不偷当前房屋,选择上一个房屋(偷或者不偷)的最大值
            a[i][0] = Math.max(a[i - 1][0], a[i - 1][1]);
            // 偷当前房屋,上一个房屋只能不偷
            a[i][1] = a[i - 1][0] + nums[i];
        }
        return Math.max(a[n - 1][0], a[n - 1][1]);
    }

	> 优化
    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 0 || nums == null) {
            return 0;
        }
        if (n == 1) {
            return nums[0];
        }
        // a[i]表示前i个屋子所偷金额达到的最大值
        int[] a = new int[n];
        a[0] = nums[0];
        a[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < n; i++) {
            // 不偷当前房屋,前i-1个屋子所偷金额达到的最大值
            // 偷当前房屋,(i - 1)个房屋只能不偷,(i - 2) 个房屋必偷
            a[i] = Math.max(a[i - 1], a[i - 2] + nums[i]);
        }
        return a[n - 1];
    }

环形结构

题解来源

	public int rob(int[] nums) {
        // 环形拆分为2个单排排列,①不偷第一个房间,②不偷最后一个房间
        int n = nums.length;
        if (n == 0) 
            return 0;
        if (n == 1) 
            return nums[0];
        // 避免方法调用溢出
        if (n == 2) 
            return Math.max(nums[0], nums[1]);
        // Arrays.copyOfRange 拷贝产生一个新数组
       return Math.max(myRob(Arrays.copyOfRange(nums, 0, n - 1)), myRob(Arrays.copyOfRange(nums, 1, n)));
    }
     public int myRob(int[] nums) {
        int n = nums.length;
        if (nums.length == 0) {
            return 0;
        }
        // a[i] 表示前i个房间所能偷的最大金额
        int[] a = new int[n];
        a[0] = nums[0];
        a[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < n; i++) {
            a[i] = Math.max(a[i-1], a[i-2] + nums[i]);
        }
        return a[n - 1];
    }

树形结构

题解来源

	public int rob(TreeNode root) {
       int[] result =  dfs(root);
       return Math.max(result[0], result[1]);
    }
     // 画一个简单的二叉树,走一下这个代码流程。不要深入递归,计算机干的才是重复的事情
    public int[] dfs(TreeNode root){
        if (root == null) {
            return new int[2];
        }
        int[] left = dfs(root.left);
        int[] right = dfs(root.right);
        // 0表示不偷当前节点,1表示偷
        int[] result = new int[2];
        // 金额最大值 = 左孩子偷或者不偷的最大值 + 右孩子偷或者不偷的最大值
        result[0] = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
        // 金额最大值 = 左孩子不偷的最大值 + 右孩子不偷的最大值 + 当前节点的值
        result[1] = left[0] + right[0] + root.val;
        return result;
    }
posted @ 2021-11-22 08:58  哟喝  阅读(56)  评论(0)    收藏  举报