1.描述:最小子序列(序列之和最小)
思路:用编程之美上的分治解法。子数组存在三种情况:
(1)左边的字数组里面arr[1...n/2]
(2)右边的子数组里面arr[n/2+1...n]
(3)要么在中间 arr[start..n/2....end];
代码:
#include<iostream>
using namespace std;
#define max 100
int findMinSubstr(int arr[],int start,int end)
{
if(start==end)return arr[start];
int left,right;
int result = max;
int mid = start+((end-start)>>1);
left = findMinSubstr(arr,start,mid);
right = findMinSubstr(arr,mid+1,end);
int i = mid - 1;
int j = mid + 1;
int sum = arr[mid];
int minsum = max;
while(i>=start){
sum += arr[i];
if(sum<minsum)minsum = sum;
i--;
}
sum = minsum;
while(j<end){
sum += arr[j];
if(sum<minsum)minsum = sum;
j++;
}
if(minsum<left)return minsum<right?minsum:right;
else return left<right?left:right;
}
int main()
{
int arr[]={-1,7,3,-3,6};
cout<<findMinSubstr(arr,0,4)<<endl;
system("pause");
return 0;
}
2.描述:最小正子序列(序列之和最小,同时满足和值要最小)
思路:
(1)先求出数组的前缀数组之和,例如:2,-3,-3,7,5=>前缀数组和为2,-1,-4,3,8(它们的索引0 1 2 3 4)
(2)对前缀数组进行排序得到:-4,-1,2,3,8(即是这样的:(-4,3) (1,1) (2,0) (3,3,) (8,4) )
(3)则最小值一定是在:-4,1,2,3,8(结果一定在当前项减去前面一项,同时满足索引大于前一项的索引)
代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define max 100
struct Item{
int value;
int rank;
};
bool cmp(const Item&a,const Item& b)
{
return a.value<b.value;
}
int operator-(const Item&a,const Item& b)
{
return a.value-b.value;
}
bool operator>(const Item&a,const Item& b)
{
return a.rank>b.rank;
}
int findMaxPositiveSubstr(int arr[],int len)
{
Item *tmp = new Item[len];
int sum = 0;
int i;
memset(tmp,0,sizeof(Item)*len);
for(int i=0;i<len;i++){
sum += arr[i];
tmp[i].value = sum;
}
for(i=0;i<len;i++)
tmp[i].rank = i;
sort(tmp,tmp+len,cmp);
int result = tmp[0].value>0?tmp[0].value:max;
for(i=1;i<len;i++){
if(tmp[i]>tmp[i-1]&&(tmp[i]-tmp[i-1])>0&&(tmp[i]-tmp[i-1])<result){
result = tmp[i]-tmp[i-1];
}
}
return result;
}
int main()
{
int arr[]={2,-3,-3,7,5};
cout<<findMaxPositiveSubstr(arr,4)<<endl;
system("pause");
return 0;
}
3.描述:最大子序列乘积
代码:
#include<iostream>
using namespace std;
#define max 0;
#define min -1;
long int findMaxSubstr(int arr[],int start,int end)
{
if(start==end)return arr[start];
long int left,right;
int mid = start+((end-start)>>1);
left = findMaxSubstr(arr,start,mid);
right = findMaxSubstr(arr,mid+1,end);
int i = mid - 1;
int j = mid + 1;
long int muilt = arr[mid];
long int minNegativeLeft = min;
long int minNegativeRight = min;
long int maxPostiveLeft = max;
long int maxPostiveRight = max;
while(i>=start){
muilt *= arr[i];
if(muilt>0){
if(muilt>maxPostiveLeft)maxPostiveLeft = muilt;
}else{
if(muilt<minNegativeLeft)minNegativeLeft = muilt;
}
i--;
}
muilt = 1;
while(j<end){
muilt *= arr[j];
if(muilt>0){
if(muilt>maxPostiveRight)maxPostiveRight = muilt;
}else{
if(muilt<minNegativeRight)minNegativeRight = muilt;
}
j++;
}
long int tmp = minNegativeLeft*minNegativeRight>maxPostiveLeft*maxPostiveRight?
minNegativeLeft*minNegativeRight:maxPostiveLeft*minNegativeRight;
if(tmp>left)return tmp>right?tmp:right;
else return left>right?left:right;
}
int main()
{
int arr[]={-1,7,3,-3,-6};
cout<<findMaxSubstr(arr,0,5)<<endl;
system("pause");
return 0;
}