• 相亲大会——求最大子串和




    题目:



    分析:

    思路一:

    要求最大的子串和,最简单粗暴的方法就是枚举法,枚举出所有可能的子串并求和,然后逐一比较,得出和最大的子串,用两重循环就可以实现。比如 a[3]={1,-2,3},第一重循环i从0到2,第二重循环j从i+1到2,这样的话,就有以下的情况:
    * 1 =1
    * 1 -2 =-1
    * 1 -2 3 =2
    * -2 =-2
    * -2 3 =1
    * 3 =3
    所以最大子串和就是3。


    思路二:

    思路一的方法可行,但是有些情况可以不用考虑,直接跳过,也就是说有些情况下第二重循环可以提前结束。这样的话可以节省一些时间。当某个时候,子串和是负数时,就可以直接跳出第二重循环了,由于对后面的情况,如果加上一个负数,就一定会比不加要小,所以后面不会是和最大的了。比如上面的例子,当出现1 -2时,和是-1,为负数,那么1 -2 3的情况就可以不考虑了,因为它的和一定会比最后一种情况3要小。同样的,出现-2后,-2 3的情况也可以不考虑,这样就可以简便一些。


    思路三:

    上面两种方法虽然可行,但都需要两重循环,思路二虽然跳过了一些情况,但还是过于复杂。这里提出第三种方法,如果理解了思路二的简化原理后,理解第三种方法就比较容易了。要求最大的子串和,可以用一个temp来进行累加,如果temp>=0,就把当前的数加入temp,当遇到temp<0时,就让temp等于当前的数。因为当temp>0时,对后面的子串来说,是使和增大,而当temp<0时,对后面的子串来说是使和减小,最大的子串和一定是出现在后面。比如a[5]={1,2,-4,5,6},temp=1,加上2就是3,对2来说是使子串和变大。temp=3,对-4来说,也是使-4变大,所以加上-4.temp=-1,对5来说是使5变小,所以不加,令temp=5,再加上6,就是最大的子串和。如果刚才加上temp=-1,对于5 6这个子串来说,他们的和就变小了。这样一来,就只需要遍历一遍就好了,一重循环就够了,大大降低了时间复杂度。



    代码:

    思路一:

    #include<stdio.h>     
    
    int main()   
    {
        int n,a[100000];   
        int i,j;   
        int max,temp;              //max记录最大子串和,temp用于累加
       
        scanf("%d",&n);   
       
        for(i=0;i<n;i++)   
            scanf("%d",&a[i]);   
           
        max=a[0];   
       
        for(i=0;i<n;i++)   
        {      
            temp=a[i];   
            if(temp>max)          //如果temp>max,就用max记录
                max=temp;   
           
            for(j=i+1;j<n;j++)   
            {   
                temp+=a[j];   
                if(temp>max)   
                    max=temp;   
            }   
        }   
       
        printf("%d
    ",max);
       
        return 0;   
     }  
    

    思路二:

    #include<stdio.h>  
    
    int main()   
    {   
        int n,a[100000];   
        int i,j;   
        int max,temp;                      //max记录最大子串和,temp用于累加
       
        scanf("%d",&n);   
       
        for(i=0;i<n;i++)   
            scanf("%d",&a[i]); 
           
        max=a[0];   
       
        for(i=0;i<n;i++)   
        {      
            temp=a[i];   
            if(temp>max)                    //如果temp>max,就用max记录
                max=temp;   
           
            for(j=i+1;j<n;j++)   
            {   
                temp+=a[j];
                if(temp<=0)            //temp<0,提前结束循环
    	            break; 
                if(temp>max)   
                    max=temp;   
            }   
        }   
       
        printf("%d
    ",max); 
      
        return 0;   
     } 
    

    思路三:

    #include<stdio.h>
    
    int main()
    {
        int n,i,a[100000];
        int temp=0;
        int max=-1001;
    
        scanf("%d",&n); 
    
        for(i=0;i<n;i++)
    	    scanf("%d",&a[i]);
    	
        for(i=0;i<n;i++)
        {
    	    if(temp<0)                 //temp<0,等于当前数
    		    temp=a[i];
    	    else                       //temp>=0,temp继续累加
    		    temp+=a[i];
    	    if(temp>max)               //如果temp>max,就用max记录
    		    max=temp;
        }
    
        printf("%d
    ",max);
    
        return 0;
    }
    


  • 相关阅读:
    圆圈中最后剩下的数字 【微软面试100题 第十八题】
    第一个只出现一次的字符 【微软面试100题 第十七题】
    从上往下打印二叉树 【微软面试100题 第十六题】
    二叉树的镜像 【微软面试100题 第十五题】
    和为s的两个数字 【微软面试100题 第十四题】
    链表中倒数第k个结点 【微软面试100题 第十三题】
    求1+2+...+n 【微软面试100题 第十二题】
    求二叉树中结点的最大距离 【微软面试100题 第十一题】
    翻转句子中单词的顺序 【微软面试100题 第十题】
    二叉搜索树的后序遍历序列 【微软面试100题 第九题】
  • 原文地址:https://www.cnblogs.com/jiuweilinghu/p/5931697.html
Copyright © 2020-2023  润新知