目录
一:打家劫舍
解题思路:
该题用动态规划求解,简单易懂
1,抢劫的房屋数少于两个情况(包含两个),如果就一个房屋,则肯定就抢他了,别无他家;如果房屋有两家,则抢劫富有的那家
2,抢劫的房屋数大于两个,这会就该想想转移方程怎么写了,小偷光顾到了第i家,这时候小偷有两个选择,偷或者不偷,假如小偷不偷第i家,则此时小偷已经偷到的钱为dp[i-1],假如小偷要偷第i家,则小偷偷到的是dp[i-2]+nums[i]。从i-2家偷过来肯定是可以并且安全的。
3,比较偷还是不偷的大小,取大的
#define MAX(x,y) (x)>(y)?(x):(y)
int rob(int* nums, int numsSize)
{
if(numsSize == 0) return 0;
if(numsSize == 1) return nums[0];
if(numsSize == 2) return MAX(nums[0],nums[1]);
int *dp = (int *)malloc(sizeof(int)*numsSize);
memset(dp,0,numsSize);
int i = 0;
int res = 0;
for(i=0; i<numsSize; i++)
{
if(i == 0)
{
dp[i] = nums[0];
continue;
}
if(i == 1)
{
dp[i] = MAX(nums[0],nums[1]);
continue;
}
dp[i] = MAX(dp[i-1],dp[i-2]+nums[i]);
res = MAX(res,dp[i]);
}
return res;
}
运行结果:
二:打家劫舍II
解题思路:
可以把上一题看做这一题的子集,头尾的房屋其是一家的,不能同时偷,那我们可以分两种情况
1,小偷从第1家开始光顾,在倒数第二家停下来
2,小偷从第2家开始光顾,在最后一家停下来
这样就完美的避免了,同时抢劫了第一家和最后一家
#define MAX(x,y) (x)>(y)?(x):(y)
int subRob(int *nums, int numsSize)
{
if(numsSize == 0) return 0;
if(numsSize == 1) return nums[0];
if(numsSize == 2) return MAX(nums[0],nums[1]);
int *dp = (int *)malloc(sizeof(int)*numsSize);
memset(dp,0,numsSize);
int i = 0;
int res = 0;
for(i=0; i<numsSize; i++)
{
if(i == 0)
{
dp[i] = nums[0];
continue;
}
if(i == 1)
{
dp[i] = MAX(nums[0],nums[1]);
continue;
}
dp[i] = MAX(dp[i-1],dp[i-2]+nums[i]);
res = MAX(res,dp[i]);
}
return res;
}
int rob(int* nums, int numsSize)
{
if(numsSize == 0) return 0;
if(numsSize == 1) return nums[0];
if(numsSize == 2) return MAX(nums[0],nums[1]);
return MAX(subRob(nums,numsSize-1),subRob(nums+1,numsSize-1));
}
运行结果:
三:打家劫舍III
该题我是看了答案理解的,也说说答案的思路吧
1,对于一个二叉树的节点,我们有两个选择,打劫或者不打劫
2,比如实例2中的节点3,打劫该节点的话,则4,5节点均不能打劫,因为与3相连,则这时候能打劫到的最大数即节点3的值加上节点4和5分支的最大值
3,不打劫节点3,则选择就比较多了,节点4和5都可以打劫也可以不打劫,只需要选出其中你的最大值即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct SubtreeStatus {
int selected;
int notSelected;
};
struct SubtreeStatus dfs(struct TreeNode *node) {
if (!node) {
return (struct SubtreeStatus){0, 0};
}
struct SubtreeStatus l = dfs(node->left);
struct SubtreeStatus r = dfs(node->right);
int selected = node->val + l.notSelected + r.notSelected;
int notSelected = fmax(l.selected, l.notSelected) + fmax(r.selected, r.notSelected);
return (struct SubtreeStatus){selected, notSelected};
}
int rob(struct TreeNode *root) {
struct SubtreeStatus rootStatus = dfs(root);
return fmax(rootStatus.selected, rootStatus.notSelected);
}
运行结果: