a.求数列 { A n } \{A_n\} {An}的最小子序列和相当于求 { − A n } \{-A_n\} {−An}的最大子序列和。本题采用书中2.4.3节和算法3类似的算法。C语言代码如下:
#include<stdio.h>
#include<stdlib.h>
int MinSubSum(int* arr, int left, int right);//求数组的最小连续子列的和
int Min3(int a, int b, int c);//求这三者最小值
int main(void)
{
int arr[] = {-14,-2,59,-11, 0,-1,2,-3 };
int length = sizeof(arr) / sizeof(int);
int left = 0;
int right = length - 1;
int MinSum = MinSubSum(arr, left, right);
printf("%d\n", MinSum);
return 0;
}
int MinSubSum(int* arr, int left, int right)
{
if (left > right)
{
printf("输入错误!\n");
exit(-1);
}
if (left == right)
return arr[left];
int mid = (left + right) / 2;
int LeftMinSum = MinSubSum(arr, left, mid); //左半部分最小和
int RightMinSum = MinSubSum(arr, mid + 1, right);//右半部分最小和
/* 求中间部分最小和 相当于 求$\{-A_n\}$的中间部分的最大子序列和 */
int i,temp;
int negative_left_max, negative_right_max;
temp = 0;
negative_left_max = -arr[mid];
for (i = mid ; i >= left; i--)
{
temp = temp - arr[i];
if (temp > negative_left_max)
negative_left_max = temp;
}
temp = 0;
negative_right_max = -arr[mid + 1];
for (i = mid + 1; i <= right; i++)
{
temp = temp - arr[i];
if (temp > negative_right_max)
negative_right_max = temp;
}
int MidMinSum = -(negative_left_max + negative_right_max);
return Min3(LeftMinSum, RightMinSum, MidMinSum);
}
int Min3(int a, int b, int c)
{
int min = a;
if (b < min)
min = b;
if (c < min)
min = c;
return min;
}
b.求数列 { A n } \{A_n\} {An}的最小正子序列和。如果 { A n } \{A_n\} {An}全为负数就返回0.
解题思路:
1 1 1.求出前n项和 S [ n ] S[n] S[n],其中 S [ 0 ] = 0 S[0]=0 S[0]=0
2 2 2.对 S [ n ] S[n] S[n]进行排序,计算 S [ i + 1 ] − S [ i ] S[i+1]-S[i] S[i+1]−S[i]的的最小值(最小值一定出现在相邻项),并且位置要满足: p o s [ i + 1 ] > p o s [ i ] pos[i+1]>pos[i] pos[i+1]>pos[i],。
详细过程可以参考:参考链接.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int sum; //用于记录前pos项和
int pos;
}NODE,*PNODE;
int MinPositiveSubSum(int* arr, int length);//求出最小正子序列和
void QuickSort(PNODE count,int left, int right);//快速排序
int FindPos(PNODE count, int left, int right);//用于排快速排序中第一个元素
int main(void)
{
int arr[] = { 4, 0, 4, -1, -1 };
int length = sizeof(arr) / sizeof(int);
int MinSum = MinPositiveSubSum(arr, length);
printf("%d\n", MinSum);
return 0;
}
int MinPositiveSubSum(int* arr, int length)
{
//初始化
PNODE count = (PNODE)malloc(sizeof(NODE) * length);
count[0].sum = 0;
count[0].pos = 0;
int i;
for (i = 1; i <= length; i++)
{
count[i].pos = i;
count[i].sum = count[i - 1].sum + arr[i-1];
}
QuickSort(count, 0, length);
int MinSum = count[0 + 1].sum - count[0].sum;
for (int i = 0; i < length; i++)
{
if (count[i].pos < count[i + 1].pos && count[i].sum < count[i + 1].sum)
{
if(MinSum> (count[i + 1].sum - count[i].sum))
MinSum = count[i + 1].sum - count[i].sum;
}
}
return MinSum;
}
void QuickSort(PNODE count,int left,int right)
{
if (left >= right)
return;
else
{
int pos = FindPos(count, left, right);
QuickSort(count, left, pos - 1);
QuickSort(count, pos + 1, right);
}
}
int FindPos(PNODE count, int left, int right)
{
if (left > right)
{
printf("2.输入错误!left=%d, right=%d\n", left, right);
exit(-1);
}
if (left == right)
return left;
int temp_sum = count[left].sum;
int temp_pos = count[left].pos;
while (left < right)
{
while (left < right && temp_sum <= count[right].sum)
right--;
count[left].sum = count[right].sum;
count[left].pos = count[right].pos;
while (left<right && temp_sum >= count[left].sum)
left++;
count[right].sum = count[right].sum;
count[right].pos = count[right].pos;
}
count[right].sum = temp_sum;
count[right].pos = temp_pos;
return right;
}
c.求数列 { A n } \{A_n\} {An}的最大子序列乘积 两个 f o r for for循环暴力计算。C语言代码如下:
#include<stdio.h>
#include<malloc.h>
int MaxSubProduct(int* arr, int length);//输入数组及其长度
int main(void)
{
int arr[] = { 1,2,-3,4,0,5,-6,7,8 };
int length = sizeof(arr) / sizeof(int);
int answer = MaxSubProduct(arr, length);
printf("最大子序列的乘积为:%d\n", answer);
return 0;
}
int MaxSubProduct(int* arr, int length)
{
int temp_product = 1;
int product = arr[0];
for (int f = 0; f < length; f++)
{
temp_product = 1;
for (int r = f; r < length; r++)
{
temp_product = temp_product * arr[r];
if (temp_product > product)
product = temp_product;
}
}
return product;
}