问题描述:
意思就是说:给定一个数组,寻找一种选取方法,使得在保证任何两个相邻元素不同时被选的条件下得到的数值总和最大。
1. 递归
设nums为数组首地址,numsSize为数组的大小,max[i]表示从第i(0 <= i < numsSize)个元素开始所能得到的最大值。则原问题描述为求max[0]。
其中nums[i]+max[i+2]表示选择第i个元素,因此第i+1个元素不能选择;max[i+1]表示不选择第i个元素,而max[i+1]=max{nums[i+1]+max[i+3], max[i+2]},很明显max[i+2]小于nums[i]+max[i+2],因此:
加上边界控制语句,代码如下:
1 int maxMoney ( int *nums, int numsSize, int startIndex) { 2 if ( startIndex >= numsSize ) { 3 return 0; 4 } else if ( startIndex == numsSize - 1) { 5 return *(nums+startIndex); 6 } 7 int first = *(nums+startIndex) + maxMoney(nums, numsSize, startIndex+2); 8 int second = *(nums+startIndex+1) + maxMoney(nums, numsSize, startIndex+3); 9 return first>second?first:second; 10 } 11 12 int rob(int* nums, int numsSize) { 13 if ( numsSize == 0) { 14 return 0; 15 } else if ( numsSize == 1 ) { 16 return *nums; 17 } else if ( numsSize == 2 ) { 18 return *nums > *(nums+1)? *nums : *(nums+1); 19 } 20 int first = *nums + maxMoney(nums, numsSize, 2); 21 int second = *(nums+1) + maxMoney(nums, numsSize, 3); 22 return first>second?first:second; 23 }
2. 迭代
当i=numsSize-1(表示只剩下最后一个元素的时候),最大的只即为nums[i];
当i=numsSzie-2(剩下最后两个元素的时候,下文其它情况依次类推),最大的情况是nums[i](选择numsSize-2)或nums[i+1](选择numsSize-1);而nums[i+1]已经在i=numsSize-1的时候进行了分析,因此不用再重复;
当i=numsSize-3时,最大值只可能是
-
- nums[i]+nums[i+2],或者
- nums[i+1];
而nums[i+1](即nums[numsSize-2])已经在第二步计算过,因此只需要记录nums[i]+nums[i+2]的值;
……
下表是一个简单的分析过程,一些不可能出现最大值的情况没有写出来。
通过上述分析可知,求max[i]时,不选择第i个元素的情况(即max[i+1])已经计算过,因此只需要增加选择第i个元素的情况,那么最终的结果就是这两个值中较大的。
而对于选择i的情况,第i+1元素由于限制条件将不能选择,因此第i+2个元素可以选可以不选:
-
- 如果选择第i+2个元素,则max[i]=nums[i]+max[i+2];
- 如果不选择第i+2个元素,则i+3个元素将必须选择(因为如果不选,则将出现连续3个元素没有选择的情况,这样无论如何都不可能得到一个整体最优的值),则max[i]=nums[i]+max[i+3]
由于max[i+2]和max[i+3]已经计算出来,因此选择其中一个最大的值作为max[i]的结果。
这样可以计算出max中所有元素的值,但所有的值都是选择当前假设条件下第一个元素的情况,不选择当前元素的情况即为前一次计算的结果。最终的结果即为max[0]和max[1]中较大的。
1 int rob(int* nums, int numsSize) { 2 if ( numsSize <= 0 ) {return 0;} 3 if ( numsSize == 1 ) {return nums[0];} 4 5 int temp1 = 0, temp2 = 0; 6 if ( numsSize == 2 ) { 7 temp1 = nums[1]; 8 temp2 = nums[0]; 9 return temp1 > temp2 ? temp1 : temp2; 10 } else if ( numsSize == 3) { 11 temp1 = nums[2] + nums[0]; 12 temp2 = nums[1]; 13 return temp1 > temp2 ? temp1 : temp2; 14 } else { 15 // maxValue[i] 表示选择第i个的最大值 16 int *maxValue = (int*)malloc(numsSize * sizeof(int)); 17 maxValue[numsSize-1] = nums[numsSize-1]; 18 maxValue[numsSize-2] = nums[numsSize-2]; 19 maxValue[numsSize-3] = nums[numsSize-1] + nums[numsSize-3]; 20 for ( int i = numsSize-4; i >= 0; i--) { 21 temp1 = nums[i] + maxValue[i+2]; 22 temp2 = nums[i] + maxValue[i+3]; 23 maxValue[i] = temp1 > temp2 ? temp1 : temp2; 24 } 25 // maxValue[0]对应第一个(下标为0)选择的最大值,maxValue[1]对应第1个不选择的最大值 26 return maxValue[0] > maxValue[1] ? maxValue[0] : maxValue[1]; 27 } 28 }