关于序列的几个算法
2012-06-06 23:34
204 查看
1.求最小子序列的和
就是对于连续的序列,找出连续序列中和最小的
例如:int a[LEN] = {4,-1,5,-2,-1,2,6,-2,1,-3};
最小的子序列就是:-2,1,-3
对于下面的最大子序列就是:4,-1,5,-2,-1,2,6。
Cpp代码
/**
*最小子序列和
*n
*/
int subMinSum(int a[], int length){
int thismin = 0, min = INT_MAX;
for(int i=0; i<length; i++){
thismin += a[i];
if(thismin < min){
min = thismin;
}else if(thismin > 0){
thismin = 0;
}
}
return min;
}
2.最大子序列的和,其思想和求最小是一样的
Cpp代码
/**
*最大子序列和
*
*/
int subMaxSum(int *a, int length){
int thismax = 0, max=INT_MIN;
for(int i=0; i<length; i++){
thismax += a[i];
if(thismax > max){
max = thismax;
}else if(thismax < 0){
thismax = 0;
}
}
return max;
}
针对上面的两种算法,效率是比较高的,但是正确性不容易看出来,需要自己仔细的揣摩和证明,但是优点也很明显,就是对数据只需要一次的扫描,顺序读入,这对于大量数据来说是很有利的,只要全部读入数据就可以得出结果,这个在算法分析一书中叫做“联机算法(on-line algorithm)”,意思就是上面描述的,线性时间完成的联机算法基本上算法完美算法。
3.求最大子序列,并记录子序列位置
这里我们肯定很容易记录下最终的位置,就是不容易确定序列的起始位置,主要是由于该算法的特性,最后想了好久才想到用:减最大的值的方法,当等于0的时候就找到起始位置了,从而确定序列范围
Cpp代码
#include <iostream>
using namespace std;
int maxsub(const int* a, int length, int* loc){
//maxsum记录最大的值,thissum记录当前的值
int maxsum=0, thissum=0, i=0;
if(length <= 0) return 0;
for(i=0; i<length; i++){
thissum += a[i];
if(maxsum < thissum){
maxsum = thissum;
loc[1] = i;
//这里有一个思想就是,为负数的子序列不可能成为最优子序列的前缀,
}else if(thissum < 0){
thissum = 0;
}
}
thissum = maxsum;
for(i=loc[1]; i>=0; i--){
thissum -= a[i];
if(thissum == 0){
loc[0] = i;
break;
}
}
return maxsum;
}
int main(){
int a[] = {2, -3, 7, -4,-2,-2,6,-2};
int loc[2]={0};
cout<<maxsub(a, 8, loc)<<endl;
cout<<"from:"<<loc[0]<<"---to:"<<loc[1]<<endl;
return 0;
}
4.最小正子序列和
这个是在一博客中看到的:/article/2088219.html
然后我有一个疑问就是,究竟什么是最小正子序列和?这个在网上找了也没有个好的答案(http://tengtime.com/a/gaoxingnenWEBkaifa/20120406/3217.html),如果哪位仁兄知道,不胜感激!!
对于下面求出的sum我也没搞的太清楚是为什么?然后又循环什么的?
Cpp代码
struct Node
{
int sum;
int xiabiao;
};
int cmp(const Node& t1,const Node& t2)
{
return t1.sum < t2.sum;
}
/**
*最小正子序列和
*n*logn
*/
int positiveSubMinSum(int *data, int len){
Node* temp = new Node[len];
temp[0].sum = data[0];
temp[0].xiabiao = 0;
for(int i=1;i<len;i++)
{
temp[i].sum = temp[i-1].sum+data[i];
temp[i].xiabiao = i;
}
//对temp.sum[]进行从小到大排序,sum[]中只有相邻的两个数才有可能 得到 最小正子序列和
sort(temp,temp+len,cmp);
int sum = INT_MAX;
for(int i=0;i<len-1;i++)
{
if(temp[i].xiabiao < temp[i+1].xiabiao)
{
if(temp[i+1].sum - temp[i].sum > 0 && temp[i+1].sum - temp[i].sum < sum)
sum = temp[i+1].sum - temp[i].sum;
}
}
delete temp;
temp=0;
return sum;
}
5.最大子序列的乘积
对网上的一些算法进行了下比较,发现这个算法还可以,比较简洁:/article/10753326.html
对该算法的说明:
这个问题其实可以简化成这样:数组中找一个子序列,使得它的乘积最大;同时找一个
子序列,使得它的乘积最小(负数的情况)。虽然我们只要一个最大积,但由于负数的
存在,我们同时找这两个乘积做起来反而方便。
我们让maxCurrent表示当前最大乘积的candidate,minCurrent反之,表示当前最小乘积
的candidate。这里我用candidate这个词是因为只是可能成为新一轮的最大/最小乘积,
而maxProduct则记录到目前为止所有最大乘积candidates的最大值。
由于空集的乘积定义为1,在搜索数组前,maxCurrent,maxProduct,minCurrent都赋为1。
假设在任何时刻你已经有了maxCurrent和minCurrent这两个最大/最小乘积的candidates,
新读入数组的元素x(i)后,新的最大乘积candidate只可能是maxCurrent或者minCurrent
与x(i)的乘积中的较大者,如果x(i)<0导致maxCurrent<minCurrent,需要交换这两个
candidates的值。
当任何时候maxCurrent<1,由于1(空集)是比maxCurrent更好的candidate,所以更新
maxCurrent为1,类似的可以更新minCurrent。任何时候maxCurrent如果比最好的
maxProduct大,更新maxProduct。
Cpp代码
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
/**
*最大子序列乘积(同时也求出了最小的子序列乘积)
*在找最大的值得时候,必须记录最小值,因为有负数存在,最小的数可能变成最大的数
*/
int mutiSubMax(int *a, int length){
int i;
int maxProduct = 1;
int minProduct = 1;
int maxCurrent = 1;
int minCurrent = 1;
for( i=0; i<length ;i++)
{
maxCurrent *= a[i];
minCurrent *= a[i];
if(maxCurrent > maxProduct)
maxProduct = maxCurrent;
if(minCurrent > maxProduct)
maxProduct = minCurrent;
if(maxCurrent < minProduct)
minProduct = maxCurrent;
if(minCurrent < minProduct)
minProduct = minCurrent;
//注意交换
if(minCurrent > maxCurrent)
swap(maxCurrent,minCurrent);
//这个必须在最后(防止为0的时候)
if(maxCurrent<1)
maxCurrent = 1;
//if(minCurrent>1)//这里不需要,因为通过交换即可,只需要一个
// minCurrent =1;
}
return maxProduct;
}
6.最长递增子序列
参考:
/article/8206086.html
http://www.programfan.com/blog/article.asp?id=13086
a,问题描述
设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值
b,问题分析
最长递增子序列可以看成一个动态规划的问题,关于动态规划可以参见:
http://hi.baidu.com/hacklzt/blog/item/81e6b8fc795d251f09244de7.html
http://www.cnblogs.com/brokencode/archive/2011/06/26/2090702.html
其实质就是:将问题细化,逐步求解
当然实际的过程相对复杂些,就拿该题来说
如:子序列{1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 }这样一个字符串的的最长递增子序列就是{1,3,4,5,6,7}或者{1,3,4,5,6,19}。
首先,该问题可以抽象为:子序列为L(1..n), A(1...i)是一个从1到i的优化的子结构,也就是最长递增子序列,求A(n)。
其次,根据上面的抽象,求的就是A(n), 那么问题就转化为求A(j)与A(1...i)(j>i)的关系(状态转移方程)。
最后,根据动态规划的概念,找的就是上面的这样一个关系,如何将A(j)与A(1...i)联系起来?从而将问题细化,L(j) = max {L(i), i<j && A(i)<A(j) } + 1;
也就是说L(j)等于之前所有的L(i)中最大的的L(i)加一。这样的L(i)需要满足的条件就是A(i)<A(j).这个推断还是比较容易理解的.就是选择j之前所有的满足小于当前数组的最大值.
然后就是将上面的关系式转换为代码,这个就很简单了。
过程如下:
Cpp代码
/**
*最长递增子序列
*
*/
#include <iostream>
#include <cstring>
using namespace std;
//利用动态规划法O(n^2)
void longestIncreaseSub(int* a, int length, int* sub){
int n = length;
//利用一个辅助数列,记录子问题的值
int *t = new int
;//需要将t所有都初始化1,t记录子序列(子问题)的最长递增子序列长度
int *p = new int
;
memset(p,0,sizeof(int));
//初始的最大子序列长度默认为1,即自身组成一个最长递增子序列
t[0]=1;
for(int i=1; i<n; i++){
t[i]=1;
for(int j=0; j<i; j++){
//这里面就是动态优化的状态转移方程
if(a[j]<a[i] && t[j]>t[i]-1){
//里面存的是(0到i)的子序列中最长递增子序列的长度
t[i]=t[j]+1;
//符合要求的子序列位置(就是上一个子序列中的最后一个值的位置)
p[i]=j;
}
}
}
int m=0,k=0;
for (int i=1;i<=n;i++)
{
if (m<t[i])
{//m存t中最大值(就是要找的最长递增子序列),i是其所在的索引
m = t[i];
k = i;
}
}
while(m>=0){
sub[m-1] = a[k];
m--;
//p[k]中存着子序列中下一个值的下标位置
k = p[k];
}
for(int d=0; d<n; d++) cout<<t[d]<<" ";
cout<<endl;
for(int d=0; d<n; d++) cout<<p[d]<<" ";
delete[] t;
delete[] p;
p = NULL;
t = NULL;
}
int main(){
int a[] = { 1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };
int length = sizeof(a)/sizeof(int);
int* sub = new int[length];
memset(sub,0,sizeof(int));//初始化sub
longestIncreaseSub(a,length, sub);
cout<<endl;
for(int k=0; k<length; k++) cout<<sub[k]<<" ";
delete[] sub;
sub = NULL;
}
7.上面的1,2,4,5的代码全部
Cpp代码
/**
*2.17
*求最小子序列和,最小正子序列和,最大子序列乘积
*
*/
#include <iostream>
#include <algorithm>
using namespace std;
#define INT_MIN -32768
#define INT_MAX 32767
//在里面有使用#define和const定义常量的比较,推荐使用const
//#define LEN 10
const int LEN = 10;
/**
*最大子序列和
*
*/
int subMaxSum(int *a, int length){
int thismax = 0, max=INT_MIN;
for(int i=0; i<length; i++){
thismax += a[i];
if(thismax > max){
max = thismax;
}else if(thismax < 0){
thismax = 0;
}
}
return max;
}
/**
*最小子序列和
*n
*/
int subMinSum(int a[], int length){
int thismin = 0, min = INT_MAX;
for(int i=0; i<length; i++){
thismin += a[i];
if(thismin < min){
min = thismin;
}else if(thismin > 0){
thismin = 0;
}
}
return min;
}
struct Node
{
int sum;
int xiabiao;
};
int cmp(const Node& t1,const Node& t2)
{
return t1.sum < t2.sum;
}
/**
*最小正子序列和
*n*logn
*/
int positiveSubMinSum(int *data, int len){
Node* temp = new Node[len];
temp[0].sum = data[0];
temp[0].xiabiao = 0;
for(int i=1;i<len;i++)
{
temp[i].sum = temp[i-1].sum+data[i];
temp[i].xiabiao = i;
}
//对temp.sum[]进行从小到大排序,sum[]中只有相邻的两个数才有可能 得到 最小正子序列和
sort(temp,temp+len,cmp);
int sum = INT_MAX;
for(int i=0;i<len-1;i++)
{
if(temp[i].xiabiao < temp[i+1].xiabiao)
{
if(temp[i+1].sum - temp[i].sum > 0 && temp[i+1].sum - temp[i].sum < sum)
sum = temp[i+1].sum - temp[i].sum;
}
}
delete temp;
temp=0;
return sum;
}
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
/**
*最大子序列乘积(同时也求出了最小的子序列乘积)
*在找最大的值得时候,必须记录最小值,因为有负数存在,最小的数可能变成最大的数
*/
int mutiSubMax(int *a, int length){
int i;
int maxProduct = 1;
int minProduct = 1;
int maxCurrent = 1;
int minCurrent = 1;
for( i=0; i<length ;i++)
{
maxCurrent *= a[i];
minCurrent *= a[i];
if(maxCurrent > maxProduct)
maxProduct = maxCurrent;
if(minCurrent > maxProduct)
maxProduct = minCurrent;
if(maxCurrent < minProduct)
minProduct = maxCurrent;
if(minCurrent < minProduct)
minProduct = minCurrent;
//注意交换
if(minCurrent > maxCurrent)
swap(maxCurrent,minCurrent);
//这个必须在最后(防止为0的时候)
if(maxCurrent<1)
maxCurrent = 1;
//if(minCurrent>1)//这里不需要,因为通过交换即可,只需要一个
// minCurrent =1;
}
return maxProduct;
}
int main(){
int a[LEN] = {4,-1,5,-2,-1,2,6,-2,1,-3};
cout<<"列表:"<<endl;
for(int i=0; i<10; i++){
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"最大子序列和:"<<subMaxSum(a, LEN)<<endl;
cout<<"最小子序列和:"<<subMinSum(a, LEN)<<endl;
cout<<"最小正子序列和:"<<positiveSubMinSum(a, LEN)<<endl;
cout<<"最大子序列乘积:"<<mutiSubMax(a, LEN)<<endl;
return 0;
}
就是对于连续的序列,找出连续序列中和最小的
例如:int a[LEN] = {4,-1,5,-2,-1,2,6,-2,1,-3};
最小的子序列就是:-2,1,-3
对于下面的最大子序列就是:4,-1,5,-2,-1,2,6。
Cpp代码
/**
*最小子序列和
*n
*/
int subMinSum(int a[], int length){
int thismin = 0, min = INT_MAX;
for(int i=0; i<length; i++){
thismin += a[i];
if(thismin < min){
min = thismin;
}else if(thismin > 0){
thismin = 0;
}
}
return min;
}
2.最大子序列的和,其思想和求最小是一样的
Cpp代码
/**
*最大子序列和
*
*/
int subMaxSum(int *a, int length){
int thismax = 0, max=INT_MIN;
for(int i=0; i<length; i++){
thismax += a[i];
if(thismax > max){
max = thismax;
}else if(thismax < 0){
thismax = 0;
}
}
return max;
}
针对上面的两种算法,效率是比较高的,但是正确性不容易看出来,需要自己仔细的揣摩和证明,但是优点也很明显,就是对数据只需要一次的扫描,顺序读入,这对于大量数据来说是很有利的,只要全部读入数据就可以得出结果,这个在算法分析一书中叫做“联机算法(on-line algorithm)”,意思就是上面描述的,线性时间完成的联机算法基本上算法完美算法。
3.求最大子序列,并记录子序列位置
这里我们肯定很容易记录下最终的位置,就是不容易确定序列的起始位置,主要是由于该算法的特性,最后想了好久才想到用:减最大的值的方法,当等于0的时候就找到起始位置了,从而确定序列范围
Cpp代码
#include <iostream>
using namespace std;
int maxsub(const int* a, int length, int* loc){
//maxsum记录最大的值,thissum记录当前的值
int maxsum=0, thissum=0, i=0;
if(length <= 0) return 0;
for(i=0; i<length; i++){
thissum += a[i];
if(maxsum < thissum){
maxsum = thissum;
loc[1] = i;
//这里有一个思想就是,为负数的子序列不可能成为最优子序列的前缀,
}else if(thissum < 0){
thissum = 0;
}
}
thissum = maxsum;
for(i=loc[1]; i>=0; i--){
thissum -= a[i];
if(thissum == 0){
loc[0] = i;
break;
}
}
return maxsum;
}
int main(){
int a[] = {2, -3, 7, -4,-2,-2,6,-2};
int loc[2]={0};
cout<<maxsub(a, 8, loc)<<endl;
cout<<"from:"<<loc[0]<<"---to:"<<loc[1]<<endl;
return 0;
}
4.最小正子序列和
这个是在一博客中看到的:/article/2088219.html
然后我有一个疑问就是,究竟什么是最小正子序列和?这个在网上找了也没有个好的答案(http://tengtime.com/a/gaoxingnenWEBkaifa/20120406/3217.html),如果哪位仁兄知道,不胜感激!!
对于下面求出的sum我也没搞的太清楚是为什么?然后又循环什么的?
Cpp代码
struct Node
{
int sum;
int xiabiao;
};
int cmp(const Node& t1,const Node& t2)
{
return t1.sum < t2.sum;
}
/**
*最小正子序列和
*n*logn
*/
int positiveSubMinSum(int *data, int len){
Node* temp = new Node[len];
temp[0].sum = data[0];
temp[0].xiabiao = 0;
for(int i=1;i<len;i++)
{
temp[i].sum = temp[i-1].sum+data[i];
temp[i].xiabiao = i;
}
//对temp.sum[]进行从小到大排序,sum[]中只有相邻的两个数才有可能 得到 最小正子序列和
sort(temp,temp+len,cmp);
int sum = INT_MAX;
for(int i=0;i<len-1;i++)
{
if(temp[i].xiabiao < temp[i+1].xiabiao)
{
if(temp[i+1].sum - temp[i].sum > 0 && temp[i+1].sum - temp[i].sum < sum)
sum = temp[i+1].sum - temp[i].sum;
}
}
delete temp;
temp=0;
return sum;
}
5.最大子序列的乘积
对网上的一些算法进行了下比较,发现这个算法还可以,比较简洁:/article/10753326.html
对该算法的说明:
这个问题其实可以简化成这样:数组中找一个子序列,使得它的乘积最大;同时找一个
子序列,使得它的乘积最小(负数的情况)。虽然我们只要一个最大积,但由于负数的
存在,我们同时找这两个乘积做起来反而方便。
我们让maxCurrent表示当前最大乘积的candidate,minCurrent反之,表示当前最小乘积
的candidate。这里我用candidate这个词是因为只是可能成为新一轮的最大/最小乘积,
而maxProduct则记录到目前为止所有最大乘积candidates的最大值。
由于空集的乘积定义为1,在搜索数组前,maxCurrent,maxProduct,minCurrent都赋为1。
假设在任何时刻你已经有了maxCurrent和minCurrent这两个最大/最小乘积的candidates,
新读入数组的元素x(i)后,新的最大乘积candidate只可能是maxCurrent或者minCurrent
与x(i)的乘积中的较大者,如果x(i)<0导致maxCurrent<minCurrent,需要交换这两个
candidates的值。
当任何时候maxCurrent<1,由于1(空集)是比maxCurrent更好的candidate,所以更新
maxCurrent为1,类似的可以更新minCurrent。任何时候maxCurrent如果比最好的
maxProduct大,更新maxProduct。
Cpp代码
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
/**
*最大子序列乘积(同时也求出了最小的子序列乘积)
*在找最大的值得时候,必须记录最小值,因为有负数存在,最小的数可能变成最大的数
*/
int mutiSubMax(int *a, int length){
int i;
int maxProduct = 1;
int minProduct = 1;
int maxCurrent = 1;
int minCurrent = 1;
for( i=0; i<length ;i++)
{
maxCurrent *= a[i];
minCurrent *= a[i];
if(maxCurrent > maxProduct)
maxProduct = maxCurrent;
if(minCurrent > maxProduct)
maxProduct = minCurrent;
if(maxCurrent < minProduct)
minProduct = maxCurrent;
if(minCurrent < minProduct)
minProduct = minCurrent;
//注意交换
if(minCurrent > maxCurrent)
swap(maxCurrent,minCurrent);
//这个必须在最后(防止为0的时候)
if(maxCurrent<1)
maxCurrent = 1;
//if(minCurrent>1)//这里不需要,因为通过交换即可,只需要一个
// minCurrent =1;
}
return maxProduct;
}
6.最长递增子序列
参考:
/article/8206086.html
http://www.programfan.com/blog/article.asp?id=13086
a,问题描述
设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值
b,问题分析
最长递增子序列可以看成一个动态规划的问题,关于动态规划可以参见:
http://hi.baidu.com/hacklzt/blog/item/81e6b8fc795d251f09244de7.html
http://www.cnblogs.com/brokencode/archive/2011/06/26/2090702.html
其实质就是:将问题细化,逐步求解
当然实际的过程相对复杂些,就拿该题来说
如:子序列{1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 }这样一个字符串的的最长递增子序列就是{1,3,4,5,6,7}或者{1,3,4,5,6,19}。
首先,该问题可以抽象为:子序列为L(1..n), A(1...i)是一个从1到i的优化的子结构,也就是最长递增子序列,求A(n)。
其次,根据上面的抽象,求的就是A(n), 那么问题就转化为求A(j)与A(1...i)(j>i)的关系(状态转移方程)。
最后,根据动态规划的概念,找的就是上面的这样一个关系,如何将A(j)与A(1...i)联系起来?从而将问题细化,L(j) = max {L(i), i<j && A(i)<A(j) } + 1;
也就是说L(j)等于之前所有的L(i)中最大的的L(i)加一。这样的L(i)需要满足的条件就是A(i)<A(j).这个推断还是比较容易理解的.就是选择j之前所有的满足小于当前数组的最大值.
然后就是将上面的关系式转换为代码,这个就很简单了。
过程如下:
Cpp代码
/**
*最长递增子序列
*
*/
#include <iostream>
#include <cstring>
using namespace std;
//利用动态规划法O(n^2)
void longestIncreaseSub(int* a, int length, int* sub){
int n = length;
//利用一个辅助数列,记录子问题的值
int *t = new int
;//需要将t所有都初始化1,t记录子序列(子问题)的最长递增子序列长度
int *p = new int
;
memset(p,0,sizeof(int));
//初始的最大子序列长度默认为1,即自身组成一个最长递增子序列
t[0]=1;
for(int i=1; i<n; i++){
t[i]=1;
for(int j=0; j<i; j++){
//这里面就是动态优化的状态转移方程
if(a[j]<a[i] && t[j]>t[i]-1){
//里面存的是(0到i)的子序列中最长递增子序列的长度
t[i]=t[j]+1;
//符合要求的子序列位置(就是上一个子序列中的最后一个值的位置)
p[i]=j;
}
}
}
int m=0,k=0;
for (int i=1;i<=n;i++)
{
if (m<t[i])
{//m存t中最大值(就是要找的最长递增子序列),i是其所在的索引
m = t[i];
k = i;
}
}
while(m>=0){
sub[m-1] = a[k];
m--;
//p[k]中存着子序列中下一个值的下标位置
k = p[k];
}
for(int d=0; d<n; d++) cout<<t[d]<<" ";
cout<<endl;
for(int d=0; d<n; d++) cout<<p[d]<<" ";
delete[] t;
delete[] p;
p = NULL;
t = NULL;
}
int main(){
int a[] = { 1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };
int length = sizeof(a)/sizeof(int);
int* sub = new int[length];
memset(sub,0,sizeof(int));//初始化sub
longestIncreaseSub(a,length, sub);
cout<<endl;
for(int k=0; k<length; k++) cout<<sub[k]<<" ";
delete[] sub;
sub = NULL;
}
7.上面的1,2,4,5的代码全部
Cpp代码
/**
*2.17
*求最小子序列和,最小正子序列和,最大子序列乘积
*
*/
#include <iostream>
#include <algorithm>
using namespace std;
#define INT_MIN -32768
#define INT_MAX 32767
//在里面有使用#define和const定义常量的比较,推荐使用const
//#define LEN 10
const int LEN = 10;
/**
*最大子序列和
*
*/
int subMaxSum(int *a, int length){
int thismax = 0, max=INT_MIN;
for(int i=0; i<length; i++){
thismax += a[i];
if(thismax > max){
max = thismax;
}else if(thismax < 0){
thismax = 0;
}
}
return max;
}
/**
*最小子序列和
*n
*/
int subMinSum(int a[], int length){
int thismin = 0, min = INT_MAX;
for(int i=0; i<length; i++){
thismin += a[i];
if(thismin < min){
min = thismin;
}else if(thismin > 0){
thismin = 0;
}
}
return min;
}
struct Node
{
int sum;
int xiabiao;
};
int cmp(const Node& t1,const Node& t2)
{
return t1.sum < t2.sum;
}
/**
*最小正子序列和
*n*logn
*/
int positiveSubMinSum(int *data, int len){
Node* temp = new Node[len];
temp[0].sum = data[0];
temp[0].xiabiao = 0;
for(int i=1;i<len;i++)
{
temp[i].sum = temp[i-1].sum+data[i];
temp[i].xiabiao = i;
}
//对temp.sum[]进行从小到大排序,sum[]中只有相邻的两个数才有可能 得到 最小正子序列和
sort(temp,temp+len,cmp);
int sum = INT_MAX;
for(int i=0;i<len-1;i++)
{
if(temp[i].xiabiao < temp[i+1].xiabiao)
{
if(temp[i+1].sum - temp[i].sum > 0 && temp[i+1].sum - temp[i].sum < sum)
sum = temp[i+1].sum - temp[i].sum;
}
}
delete temp;
temp=0;
return sum;
}
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
/**
*最大子序列乘积(同时也求出了最小的子序列乘积)
*在找最大的值得时候,必须记录最小值,因为有负数存在,最小的数可能变成最大的数
*/
int mutiSubMax(int *a, int length){
int i;
int maxProduct = 1;
int minProduct = 1;
int maxCurrent = 1;
int minCurrent = 1;
for( i=0; i<length ;i++)
{
maxCurrent *= a[i];
minCurrent *= a[i];
if(maxCurrent > maxProduct)
maxProduct = maxCurrent;
if(minCurrent > maxProduct)
maxProduct = minCurrent;
if(maxCurrent < minProduct)
minProduct = maxCurrent;
if(minCurrent < minProduct)
minProduct = minCurrent;
//注意交换
if(minCurrent > maxCurrent)
swap(maxCurrent,minCurrent);
//这个必须在最后(防止为0的时候)
if(maxCurrent<1)
maxCurrent = 1;
//if(minCurrent>1)//这里不需要,因为通过交换即可,只需要一个
// minCurrent =1;
}
return maxProduct;
}
int main(){
int a[LEN] = {4,-1,5,-2,-1,2,6,-2,1,-3};
cout<<"列表:"<<endl;
for(int i=0; i<10; i++){
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"最大子序列和:"<<subMaxSum(a, LEN)<<endl;
cout<<"最小子序列和:"<<subMinSum(a, LEN)<<endl;
cout<<"最小正子序列和:"<<positiveSubMinSum(a, LEN)<<endl;
cout<<"最大子序列乘积:"<<mutiSubMax(a, LEN)<<endl;
return 0;
}
相关文章推荐
- [算法基础]几个关于递归算法的练习题
- 关于最长上升子序列的算法 简单dp
- 关于动态规划的几个算法
- 关于子序列最大和的几种算法
- 关于JVM的几个垃圾收集算法思想
- 积跬步至千里——算法强化训练(5)关于类的几个操作
- C++11新特性应用--介绍几个新增的便利算法(关于最大值和最小值的算法)
- C++11新特性应用--介绍几个新增的便利算法(关于最大值和最小值的算法)
- 关于一个算法题的想法:1000瓶汽水,每喝3瓶赚一瓶,最终喝了多少瓶,剩几个空瓶?
- 关于几个统计值以及matlab的算法
- 关于JVM的几个垃圾收集算法思想
- 几个有用的网站/博客 关于JAVA 算法。
- 图的概念和关于图的几个算法
- 关于最长不下降子序列O(nlogn)算法
- 几个关于串的小算法题:最小K个数、连续子数组的最大和、字符串全排列求法、数组循环移位
- 关于最短路的几个算法
- 关于链表的几个常见的算法
- 基础的东西,关于二叉树的几个算法 C#的
- OFBiz entity engine 关于数据库自增序列生成算法的源码解读
- 「算法精解_C语言描述」链表_关于链表特点的几个问与答