一、leetcode题目
1.打家劫舍 III
题目描述
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root
。
除了 root
之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root
。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
2.测试用例
输入:
[3,2,3,null,3,null,1]
输出:
7
解释:
小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
提示
- 树的节点数在 [ 1 , 1 0 4 ] [1, 10^4] [1,104] 范围内
- 0 < = N o d e . v a l < = 1 0 4 0 <= Node.val <= 10^4 0<=Node.val<=104
3.思路
这个题目是我刻意挑的,学习一下树形dp
,之前没有接触树形dp
的题目。当前阶段的值可由上一阶段推导而来。但每个阶段可由两种状态偷当前房屋
与不偷当前房屋
。两种状态都需要保存。
- 偷取当前房屋能够取得的最大价值: v a l = l e f t d p [ 0 ] ( 不偷左孩子房屋的价值 ) + r i g h t d p [ 0 ] ( 不偷右孩子房屋的价值 ) + c u r . v a l ( 当前房屋的价值 ) val = leftdp[0](不偷左孩子房屋的价值)+rightdp[0](不偷右孩子房屋的价值)+cur.val(当前房屋的价值) val=leftdp[0](不偷左孩子房屋的价值)+rightdp[0](不偷右孩子房屋的价值)+cur.val(当前房屋的价值)
- 不偷取当前房屋能够取得的最大价值: v a l = m a x ( l e f t d p [ 0 ] , l e f t d p [ 1 ] ) + m a x ( r i g h t d p [ 0 ] + r i g h t d p [ 1 ] ) ( 左右孩子偷与不偷的最大值之和 ) val=max(leftdp[0],leftdp[1]) + max(rightdp[0] + rightdp[1])(左右孩子偷与不偷的最大值之和) val=max(leftdp[0],leftdp[1])+max(rightdp[0]+rightdp[1])(左右孩子偷与不偷的最大值之和)
4.算法实现
class Solution {
public int rob(TreeNode root) {
int[] res = dfs(root);
return Math.max(res[0], res[1]);
}
private int[] dfs(TreeNode node){
if(node == null) return new int[]{0, 0};
int[] leftdp = dfs(node.left);
int[] rightdp = dfs(node.right);
int val1 = node.val + leftdp[0] + rightdp[0];
int val2 = Math.max(leftdp[0], leftdp[1]) + Math.max(rightdp[0], rightdp[1]);
return new int[]{val2, val1};
}
}
二、蓝桥题目
1.砝码称重
题目描述
你有一架天平和
N
N
N 个砝码,这
N
N
N 个砝码重量依次是
W
1
,
W
2
,
⋅
⋅
⋅
,
W
N
W_1, W_2, · · · , W_N
W1,W2,⋅⋅⋅,WN。
请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。
输入描述
输入的第一行包含一个整数 NN。
第二行包含 N N N 个整数: W 1 , W 2 , W 3 , ⋅ ⋅ ⋅ , W N W_1, W_2, W_3, · · · , W_N W1,W2,W3,⋅⋅⋅,WN。
输出描述
输出一个整数代表答案。
2.测试用例
输入:
3
1 4 6
输出:
10
3.思路
每个砝码可以有两种状态,放在天平左边(-),放在天平右边(+)。
使用一个set存放所有可能性,再使用一个set存放能组成的正整数合计。最终结果为存放正整数set的长度。
4.算法实现
import java.util.Scanner;
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n = scan.nextInt();
HashSet<Integer> set = new HashSet<>();
HashSet<Integer> res = new HashSet<>();
for(int i = 0; i < n; i++){
int cur = scan.nextInt();
res.add(cur);
for(int k = 0; k < 2; k++){
cur = -cur;
List<Integer> list = new ArrayList<>(set);
for(int num : list){
int a = num + cur;
set.add(a);
if(a > 0) res.add(a);
}
}
set.add(cur);
set.add(-cur);
}
System.out.println(res.size());
scan.close();
}
}