C/C++有关子数组和与长度问题

1、给定一个数组,当然其中有很多子数组,在所有子数组的组合中,找到连续累加和最大的那个,返回累加和

解题思路:一般思维就是找到所有的子数组,并比较所有子数组长度和,时间复杂度 O(N^2)   n*(n-1)*(n-2)....
另一种方法就是客观思考,求累加和最大的,则子数组的第一个位置应该是正数,我们定义两个变量,用cur表示依次累加数组的值,利用ros储存cur中最大值,每当cur累加的值小于0时,清空cur的值,令cur =0;重复上述工作,只需要每个元素遍历一次就可以得到结果
int MaxSum(int[] array)
{
    if(array==NULL || array.length == 0)
         return 0;
    int ros = array[0];
    int cur = array[0];
    for(int i = 1;i<array.length;i++)
    {
       if(cur<0)
      {
          cur = 0;
      }
      else
      {
          cur = array[i]+cur;
      }
      if(cur>ros)
      {
          ros= cur;
      }
    }
    return ros;
}

2、给定一个数组,其中有很多子数组,在所有两个子数组的组合中,找到累加和最大的一组,要求两个子数组无重合部分,最后返回累加和(时间复杂度为O(n))

解题思路:利用两个辅助数组left[] 与right[],  left[]数组用来存放从左往右子数组最大值(利用第一题的思路),right[]数组用来从后往前存储最大子数组的累加和,随后再一次从第一个位置往后把sum  =left[i] 与 right[i+1],i后移,每次判断sum的值大小,找到最大的返回
int MaxSum(int[] array)
{
    if(array==NULL || array.length < 2)// 只有一个元素构不成两个子数组
         return 0;
     int[] right = new int[array.length];
     right[array.length-1] = array[array.length-1];
     int cur = array[array.length-1];
     for(int i =array.length-2;i>= 0;i--)//从后往前,依次将子数组最大值 存储在相应位置
     {
         cur = cur<0? 0: cur;
         cur = cur+array[i];
         if(cur>right[i+1])
         {
             right[i] = cur;
         }
         else
         {
            right[i] = right[i+1];
         }
     }
int ros = array[0] + right[1]//要返回的两个不重复的子数组的累加和最大值
int cur = array[0];
int lmax = array[0];//从左往右记录子数组的最大值
     for(int i=1;i<arrar[array.length];i++)
     {
        cur =cur<0? 0:cur;
        cur = cur +array[i];
        if(cur>lmax)
      {
          lmax= cur;
      }
      ros = ros<(lmax + right[i+1])?lmax + right[i+1]:ros;
      }
      return ros;

3、未排序的正数数组中累加和为给定值的最长子数组长度
eg: 2,3,1,1,1,1,1,4,1,2,3 假定给定值为5 则最长子数组为1,1,1,1,1,则长度为5

解题思路:利用两个指针left与right,开始同时指向数组首元素,让一个指针(right)依次后移,直到子数组累加和等于给定值,计算并保存之间长度,当累加和值小于等于给定值,right++;当累加和值大于给定值,则left++,时间复杂度为O(n),空间复杂度为n(1)
int GetMaxLength(int[] array,int key)
{
    if(array == NULL || array.length == 0 || key<= 0)
    return 0;
    int left = 0;
    int right = 0;
    int sum = array[0];
    int len = 0;
    while(right<array.length)  //结束条件
    {
        if(sum == key) //如果等于给定值
        { 
           if(len <right-left+1)//保存子数组长度的最长者
              len = right -left+1; 
              sum = sum-array[left++];//计算新的sum(left后移,计算子数组大小)
        }
        else if(sum <key)
        {
          right++;//右数组后移
          if(right == array.length)//判断是否数组结尾
              break;
          sum = sum+array[right];//right后移,计算新的sum大小
        }
        else
        {
            sum = sum-array[left];
            left++;
        }
    }
   return len ;




}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值