最小正序列和

#include <iostream>
#include <algorithm>
using namespace std;
//最小正子序列和(minimun subsequences sum)
const int MAXINT=999999;
struct Node
{
    int sum;
    int xiabiao;
    
};
int cmp(const Node& t1,const Node& t2)
{
    return t1.sum < t2.sum;
}

//nlogn
int minPositiveSubsequenceSum(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 = MAXINT;
  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;
}

//最小子序列和(minimun subsequences sum),logn
int minSubsequenceSum(int data[],int len)
{
    int curMinSum = data[0];
    int minSum= data[0];
    for(int i=1;i<len;i++)
    {
      if(curMinSum >= 0)
      curMinSum = data[i];
      else
      curMinSum = curMinSum + data[i];
      
      if(curMinSum < minSum)
      minSum = curMinSum;      
    }
    return minSum;
}
int main()
{
 int data[]={4,-1,5,-2,-1,2,6,-2};
 int len =sizeof(data)/sizeof(data[0]);
 cout<<minPositiveSubsequenceSum(data,len)<<endl;
 cout<<minSubsequenceSum(data,len)<<endl;
 system("pause");
 return 0;    
}

数对之差的最大值 

题目:在数组中,数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。例如在数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是11,是16减去5的结果。

解法二:转化成求解子数组的最大和问题

接下来再介绍一种比较巧妙的解法。如果输入一个长度为

n的数组numbers,我们先构建一个长度为n-1的辅助数组diff,并且diff[i]等于numbers[i]-numbers[i+1]0<=i<n-1)。如果我们从数组diff中的第i个数字一直累加到第j个数字(j > i),也就是diff[i] + diff[i+1] + … + diff[j] = (numbers[i]-numbers[i+1]) + (numbers[i + 1]-numbers[i+2]) + ... + (numbers[j] – numbers[j + 1]) = numbers[i] – numbers[j + 1]

分析到这里,我们发现原始数组中最大的数对之差(即numbers[i] – numbers[j + 1])其实是辅助数组diff中最大的连续子数组之和。如下代码:

int MaxDiff_Solution2(int numbers[], unsigned length)

{

    if(numbers == NULL || length < 2)

        return 0;

 

    int* diff = new int[length - 1];

    for(int i = 1; i < length; ++i)

        diff[i - 1] = numbers[i - 1] - numbers[i];

 

    int currentSum = 0;

    int greatestSum = 0x80000000;

    for(int i = 0; i < length - 1; ++i)

    {

        if(currentSum <= 0)

            currentSum = diff[i];

        else

            currentSum += diff[i];

 

        if(currentSum > greatestSum)

            greatestSum = currentSum;

    }

 

    delete[] diff;

 

    return greatestSum;

} 


解法三:动态规划法

既然我们可以把求最大的数对之差转换成求子数组的最大和,而子数组的最大和可以通过动态规划求解,那我们是不是可以通过动态规划直接求解呢?下面我们试着用动态规划法直接求数对之差的最大值。

我们定义diff[i]是以数组中第i个数字为减数的所有数对之差的最大值。也就是说对于任意hh < i),diff[i]≥number[h]-number[i]diff[i]0≤i<n)的最大值就是整个数组最大的数对之差。

假设我们已经求得了diff[i],我们该怎么求得diff[i+1]呢?对于diff[i],肯定存在一个hh < i),满足number[h]减去number[i]之差是最大的,也就是number[h]应该是number[i]之前的所有数字的最大值。当我们求diff[i+1]的时候,我们需要找到第i+1个数字之前的最大值。第i+1个数字之前的最大值有两种可能:这个最大值可能是第i个数字之前的最大值,也有可能这个最大值就是第i个数字。第i+1个数字之前的最大值肯定是这两者的较大者。我们只要拿第i+1个数字之前的最大值减去number[i+1],就得到了diff[i+1]

int MaxDiff_Solution3(int numbers[], unsigned length)

{

    if(numbers == NULL || length < 2)

        return 0;

 

    int max = numbers[0];

    int maxDiff =  max - numbers[1];

 

    for(int i = 2; i < length; ++i)

    {

        if(numbers[i - 1] > max)

            max = numbers[i - 1];

 

        int currentDiff = max - numbers[i];

        if(currentDiff > maxDiff)

            maxDiff = currentDiff;

    }

 

    return maxDiff;

}


在上述代码中,max表示第i个数字之前的最大值,而currentDiff表示diff[i] 0≤i<n),diff[i]的最大值就是代码中maxDiff



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值