最小最序列和以及最小正子序列

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;  
}  


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值