2.三角形最小路径和,打家劫舍
1.三角形最小路径和
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.打家劫舍
单排排列
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;
}

浙公网安备 33010602011771号