198. House Robber
求解思路: 动态规划
对于每一个房间都有两个状态:选择 、 不选择
定义变量fx[i]
:第i节点选择时,截止到i节点所取得的最大值
定义变量gx[i]
:第i节点不选择时,截止到i节点所取得的最大值
则状态转移方程:
f
x
[
i
]
=
n
u
m
s
[
i
]
+
g
x
(
n
u
m
s
[
i
−
1
]
)
g
x
[
i
]
=
M
a
t
h
.
m
a
x
(
f
x
[
i
−
1
]
,
g
x
[
i
−
1
]
)
fx[i]= nums[i] + gx(nums[i-1]) \\ gx[i] = Math.max(fx[i-1], gx[i-1])
fx[i]=nums[i]+gx(nums[i−1])gx[i]=Math.max(fx[i−1],gx[i−1])
class Solution {
public int rob(int[] nums) {
int size = nums.length;
if(size == 0){
return 0;
}
int[] fx = new int[size];
int[] gx = new int[size];
fx[0] = nums[0];
gx[0] = 0;
for(int i=1; i<size; i++){
fx[i] = nums[i] + gx[i-1];
gx[i] = Math.max(fx[i-1], gx[i-1]);
}
return Math.max(fx[size-1], gx[size-1]);
}
}
213. House Robber II
本题与198核心思想相同,与198的区别在于本题的数据是一个环状,所以需要保证第一个元素与最后一个元素不能同时被选取。
将问题拆分为
- 第一个元素不选取,
nums[1..size]
中的最大值 - 最后一个元素不选取,
nums[0..size-1]
中的最大值
综上两种情况,合并为选取两种情况中的最大值。
class Solution {
public int rob(int[] nums) {
int size = nums.length;
if(size == 0){
return 0;
}
if(size == 1){
return nums[0];
}
return Math.max(getResult(nums, 0, size-1), getResult(nums, 1, size));
}
public int getResult(int[] nums, int start, int end){
int size = end;
int[] fx = new int[size];
int[] gx = new int[size];
fx[start] = nums[start];
gx[start] = 0;
for(int i=start+1; i<end; i++){
fx[i] = nums[i] + gx[i-1];
gx[i] = Math.max(fx[i-1], gx[i-1]);
}
return Math.max(fx[end-1], gx[end-1]);
}
}
337. House Robber III
求解思路:动态规划
每一个节点都有两个状态:选择、不选择。
定义变量fx(node)
:node节点选择时,以node为根的子树所取得的最大值
定义变量gx(node)
:node节点不选择时,以node为根的子树所取得的最大值
选择当前节点,则不能选择子节点
不选择当前节点,则左右子节点可选也可不选
则状态转移方程:
f
x
(
n
o
d
e
)
=
n
o
d
e
.
v
a
l
u
e
+
g
x
(
n
o
d
e
.
l
e
f
t
)
+
g
x
(
n
o
d
e
.
r
i
g
h
t
)
g
x
(
n
o
d
e
)
=
M
a
t
h
.
m
a
x
(
f
x
(
n
o
d
e
.
l
e
f
t
)
,
g
x
(
n
o
d
e
.
l
e
f
t
)
)
+
M
a
t
h
.
m
a
x
(
f
x
(
n
o
d
e
.
r
i
g
h
t
)
,
g
x
(
n
o
d
e
.
r
i
g
h
t
)
)
fx(node) = node.value + gx(node.left) + gx(node.right) \\ gx(node) = Math.max(fx(node.left), gx(node.left)) + Math.max(fx(node.right), gx(node.right))
fx(node)=node.value+gx(node.left)+gx(node.right)gx(node)=Math.max(fx(node.left),gx(node.left))+Math.max(fx(node.right),gx(node.right))
代码实现:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
/**
* f(x) = g(x.left) + g(x.right)
* g(x) = Math.max(g(x.left), f(x.left)) + Math.max(g(x.right), f(x.right))
*/
class Solution {
Map<TreeNode, Integer> fx = new HashMap<>();
Map<TreeNode, Integer> gx = new HashMap<>();
public int rob(TreeNode root) {
//将null加入到map,保证搜索到叶节点时,其左右儿子返回0
fx.put(null, 0);
gx.put(null, 0);
dfs(root);
return Math.max(fx.get(root), gx.get(root));
}
public void dfs(TreeNode cur){
if(cur == null){
return;
}
dfs(cur.left);
dfs(cur.right);
fx.put(cur, cur.val + gx.get(cur.left) + gx.get(cur.right));
gx.put(cur, Math.max(fx.get(cur.left), gx.get(cur.left))+ Math.max(fx.get(cur.right), gx.get(cur.right)));
}
}