Maximum Subarray & Maximum Product Subarray
这两个题目比较相似,我们可以先来看一下两个题目:
这两个题目都需要求得子数组相应的最大值,第一个是子数组的和,第二个是子数组的乘积。这个问题可以延伸到类似于这样求子数组的问题中去。
该类问题我采用的是动态规划的算法来解决。
53
这道题中,如需求得 到原数组第i个元素为止,能够得到的子数组最大和,那么就只需通过加和 到第i-1个元素为止的子数组最大和加上第i个元素,或者是第i个元素本身。即:
int maxSubArray(int *nums, int numsSize) {
int *temp = (int*)malloc(sizeof(int)*numsSize);
temp[0] = nums[0];
for (int i = 1; i < numsSize; i++) {
if (temp[i - 1] <= 0) temp[i] = nums[i];
else temp[i] = temp[i - 1] + nums[i];
}
int max = temp[0];
for (int i = 1; i < numsSize; i++) {
if (temp[i] > max) max = temp[i];
}
return max;
}
这个代码非常简洁,其核心思想就是用temp数组来存储f(i),使得temp数组中存储的是其对应下标的最大子数组和,而迭代的核心则是,在计算temp[i]时,若发现temp[i-1]小于等于0,则直接拷贝nums[i]到temp[i]中;若大于0,则将nums[i] + temp[i-1]加入到temp[i]中,并以次法迭代。
对temp数组进行更新后,遍历数组,找出最大值,输出。
152
这个题我们也可以参考前面的思想,但是需要做一些改动。在求和问题中,我们可以通过前一个的状态来做出判定,但是在乘积问题中,有可能出现,负负得正的情况,会使得原来比较小的值,直接因为符号的转换而变成较大的值。因此在这个问题中,我们不仅要记录最大的乘积,而且还要记录最小的乘积(这些乘积往往为负值或者0),最后,为了省去最后一轮的遍历求最大值,我们也可以准备一个结果数组,具体的代码如下:
int maxProduct(int* nums, int numsSize) {
int *tempMax = (int*)malloc(sizeof(int)*numsSize);
int *tempMin = (int*)malloc(sizeof(int)*numsSize);
int max;
tempMax[0] = tempMin[0] = max = nums[0];
for (int i = 1; i < numsSize; i++) {
int tempMaxValue = nums[i] * tempMax[i - 1];
int tempMinValue = nums[i] * tempMin[i - 1];
tempMax[i] = Max(tempMaxValue, tempMinValue, nums[i]);
tempMin[i] = Min(tempMaxValue, tempMinValue, nums[i]);
if (tempMax[i] > max) max = tempMax[i];
}
return max;
}
其中Max和Min是表示求三个值中的最大值和最小值,在这里不给出具体代码了。