[LeetCode]198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

简言之就是给出n个数,不能取相邻的两个数,如何取到它们的最大和?

解题思路

对于a1~ai这i个数,能取到的最大和为max[i],那么
max[i]为max[i-2]+ai和max[i-1]两者的最大值,即

max[i] = max(max[i-2]+ai,  max[i-1]);

这里会有个疑问,有可能取到max[i-1]时,并没有取ai-1这个数,而是取的ai-2这个值,max[i]可以等于max[i-1]+ai,但是这时,其实max[i-1]等于max[i-2], 那么max[i] = max(max[i-2]+ai, max[i-1])在这个时候也没有问题。

按照这个公式,求出max[1], max[2]之后,就能依次求出后面的最大值了。同理,将max数组起始值改为0也是一样。

代码
#include 
#include 

#define max(a,b) (a)>(b)?(a):(b)

/**
 * Time Limit Exceeded
 *
int rob(int *nums, int numsSize) {
    if(numsSize == 0)
        return 0;
    else if(numsSize == 1)
        return nums[0];
    else if(numsSize <= 2)
        return max(nums[0], nums[1]);

    return max(rob(nums, numsSize-2)+nums[numsSize-1], rob(nums, numsSize-1));
}
 */

int rob(int *nums, int numsSize) {
    if(numsSize == 0)
        return 0;
    else if(numsSize == 1)
        return nums[0];

    int *max = malloc(sizeof(int) * numsSize);
    max[0] = nums[0];
    max[1] = max(nums[0], nums[1]);
    int i = 0;
    for(i = 2; i < numsSize; i++) {
        max[i] = max(max[i-2]+nums[i], max[i-1]);
    }

    return max[numsSize-1];
}

int main() {
    int nums[] = {1,10,2,5,6,8,3,9};
 
    assert(rob(nums, 8)==32);

    return 0;
}

你可能感兴趣的:([LeetCode]198. House Robber)