• 数组的最大连续子序列


    今天在网上看到的这道题目:

    一个有N个元素的整型数组arr,有正有负,数组中连续一个或多个元素组成一个子数组,这个数组当然有很多子数组,求子数组之和的最大值。例如:[0,-2,3,5,-1,2]应返回9,[-9,-2,-3,-5,-3]应返回-2。

    开始感觉貌似也没有那么难,就直接想循环遍历+动态规划的方法写即可。O(n2)的复杂度,感觉略大,想到上次关于最大子矩阵方法适合的O(n)的方法,感觉这个问题肯定也有这样的解法。在网上搜罗了一下,果真有各种简单的方法,仔细一看,这些方法之间还有关联性,这真的是一种思维方式的不同。

    在我以前的想法中,只要能解决问题就行了,但是最近看了很多资料,觉得很多东西都不是自己开始以为的那么简单,很多东西都是需要深入研究学习的,感觉自己真的有很多不懂的地方。只想对自己说:加油,zxh。

    废话不多说,代码、详细注释和思维流程都在这里:

     1 //根据动态规划方法,另外设置一个数组subSum[i][j]表示序列i-j的元素的和;
     2 //由题意知道:
     3 //subSum[i][j]=arr[j]  i==j
     4 //subSum[i][j]=subSum[i][j-1]+arr[j]  j<j
     5 //当arr[j]<0时候,subSum[i][j]<subSum[i][j-1]当前的max判断可以省略
     6 int maxSubArr(int arr[],int len){
     7     int sum=INT_MIN,i,j,end;
     8     if(len<=0) return sum;
     9     int **subSum=(int**)malloc(sizeof(int*)*len);
    10     for(j=0;j<len;j++)
    11     {
    12         subSum[j]=(int*)malloc(sizeof(int)*len);
    13     }
    14 
    15     for (i=1;i<len+1;i++)//不同长度
    16     {
    17         for(j=0;j<=len-i;j++)//不同起始下标
    18         {
    19             end=j+i-1;
    20             if(end==j)
    21                 subSum[j][end]=arr[end];
    22             else
    23                 subSum[j][end]=arr[end]+subSum[j][end-1];
    24             if(arr[end]>0 )sum=max(sum,subSum[j][end]);
    25         }
    26     }
    27 
    28     for(j=0;j<len;j++)
    29     {
    30         free(subSum[j]);
    31     }
    32     free(subSum);
    33 
    34     return sum;
    35 }
    36 
    37 //DP求解方法
    38 //可以对数组中最后那一个元素进行分析,arr[len-1],最长子序列跟这个arr[len-1]的关系:
    39 //arr[len-1]就是所要求的最长子序列max=arr[len-1]
    40 //arr[len-1]是最长子序列的结尾,则有max=arr[len-1]+max[len-2]
    41 //arr[len-1]跟最长子序列无关,即max=arr[len-2]
    42 //end[i]表示以arr[i]为结尾的所有子序列中和的最大值
    43 //all[i]表示从0-i中的序列中和最大的子序列的和
    44 //这个只是为了表达清楚,我们其实还可以进一步优化,减少空间复杂度
    45 int maxSubArr2(int arr[],int len){
    46     int end[30],all[30];
    47     int i=0;
    48     end[i]=all[i]=arr[0];
    49     for (i=1;i<len;i++)
    50     {
    51         end[i]=max(arr[i],end[i-1]+arr[i]);
    52         all[i]=max(end[i],all[i-1]);
    53     }
    54     return all[i-1];
    55 }
    56 //maxSubArr2的优化版本
    57 int maxSubArr3(int arr[],int len){
    58     int end,all;
    59     int i=0;
    60     end=arr[0];
    61     all=arr[0];
    62     for (i=1;i<len;i++)
    63     {
    64         end=max(arr[i],end+arr[i]);
    65         all=max(end,all);
    66     }
    67     return all;
    68 }
    69 //另一个改进版本
    70 //71 //end=max(arr[i],end+arr[i]);
    72 //all=max(end,all);
    73 //这两句,我们可以看到,end是取的arr[i]和arr[i]+end的最大值,那这两个值只有在end<0的情况下才取arr[i]
    74 //也就是当end<0时候就重新累加,丢弃掉原来的结果
    75 //那么过程就出来了,就是一直累加,每当遇到累加和小于0的时候就从头开始
    76 int maxSubArr4(int arr[],int len){
    77     int sum=arr[0],maxVal=INT_MIN;
    78     int i=0;
    79     for (i=1;i<len;i++)
    80     {
    81         if (sum<0) sum=arr[i];
    82         else sum+=arr[i];
    83 
    84         maxVal=max(sum,maxVal);
    85     }
    86     return maxVal;
    87 }

    巨人的肩膀:http://www.ahathinking.com/archives/120.html

  • 相关阅读:
    javascript入门教程笔记
    杭电2025
    杭电 2024
    杭电2019
    UEditor编辑器上传图片开发流程
    js操作textarea方法集合
    ueditor编辑器和at.js集成
    js分页算法
    js获取url中的参数
    第7章函数表达式笔记
  • 原文地址:https://www.cnblogs.com/havePassed/p/3900103.html
Copyright © 2020-2023  润新知