求子数组的最大和及下标

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/

声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,故原出处已不好查到,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。

题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

  例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。下标为[2,6]。

  若是时间复杂度为O(n^2),相信大家都容易解决,我用了双重循环的方法,类似于穷举法。但这里要求时间复杂度为O(n),则比较麻烦,在网上也找到不同的解决方案,其中,利用贪心算法的方式解决是相对简单的。

算法思想:

  1)首先初始化子数组和的最大值max为最小负整数-(1<<31),数组元素和sum为0,字数组的起始下标start=0和终止下标end=0。

  2)从第一个元素开始循环遍历数组:

    a.若相加后的sum为正,且sum>max,则max=sum;若sum<0,则sum=0。

    b.否则,若sum<0,则sum=0。

算法的java实现:

 1 package com.interview;
 2 /**
 3  *
 4  * @author wjh
 5  *
 6  */
 7 public class _3MaxArrSum {
 8
 9     /**
10      * @param args
11      */
12     public static void main(String[] args) {
13         int[] a = {7,-2,-2, -2, 3, 10};//{1, -2, 3, 10, -4, 7, 2, -5};
14         maxSum1(a);
15         //maxSum2(a);
16     }
17
18     //用二重循环  , 时间复杂度为O(n)
19     private static void maxSum1(int[] a){
20         int n = a.length;
21         int max=  -(1<<31);  //用来保存最大值,初始化为最小的整数
22         int sum = 0;
23         int start = 0;       //开始下标
24         int end = 0;         //结束下标
25         for(int i=0;i<n;i++){
26             int temp = sum;  //保存上一次的sum
27             sum +=a[i];
28             //如果前面选中的子数组之和已经<=0,而a[i]>0,则前面部分已经可以抛弃了,start和end从新指向当前的i
29             if(temp==0&&sum>temp){ //若不求字数组的下标,则用不着这个分支
30                 start=i;
31                 end = i;
32             }
33             if(sum>0&&sum>max){    //设上一个正数为a[j],当a[i]>0,并且 a[i]+ a(j,i-1] 之间的<=0的数之和大于  0
34                 max=sum;
35                 end = i;
36             }
37             else if(sum<0){      //sum<0则将sum归0,若此处是else if,当形如{-2,2}的数据时第一次循环后max=sum=-2,
38                 sum=0;      //进入第二次循环时,temp=-2;sum=0;    不会进入第一个分支,start不动,进入第二个分支时max=0;下标和结果都错误
39             }
40         }
41         System.out.println("最大值为:"+max);
42         System.out.println("取得最大值时数组的起始和终止下标为: ["+start+","+end+"]");
43     }
44     /**    里面的条件分支可改为:
45      *         if(temp==0&&sum>temp){ //
46                 start=i;
47                 end = i;
48             }
49             if(sum>max){    //此时的sum肯定为正
50                 max=sum;
51                 end = i;
52             }
53             if(sum<0){      //
54                 sum=0;      //
55             }
56      */
57
58     //用二重循环  , 时间复杂度为O(n^2)
59     private static void maxSum2(int[] a){
60         int n = a.length;
61         int max=  -(1<<31);  //用来保存最大值,初始化为最小的整数
62         int start = 0;       //开始下标
63         int end = 0;         //结束下标
64         for(int i=0;i<n;i++){
65             int sum = 0;
66             for(int j=i;j<n;j++){
67                 sum += a[j];
68                 if(sum>max){
69                     max = sum;
70                     start = i;
71                     end = j;
72                 }
73             }
74         }
75         System.out.println("最大值为:"+max);
76         System.out.println("取得最大值时数组的起始和终止下标为: ["+start+","+end+"]");
77     }
78 }

  博主白杨的文章 http://xingyunbaijunwei.blog.163.com/blog/static/7653806720122273022366/ 给了我很大的帮助,在此致谢!

时间: 2024-12-08 08:03:34

求子数组的最大和及下标的相关文章

【编程题目】求子数组的最大和 ☆

3.求子数组的最大和(数组)题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为 O(n).例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,因此输出为该子数组的和 18. 算法里学过,动态规划.具体思路想不起来了,看了看书.要动态算1-i个元素中必须包括第i个元素的最大子段和C[i],A是原始序列 C[i + 1] = A[

微软算法100题03 求子数组的最大和

3.求子数组的最大和题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n).例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18 思路:使用辅助变量max 记录子数组的最大和,从数组头开始遍历,如果数组元素与之前的总和的sum是负数,则重置sum结果为零,否则将得到的sum值与max比较 如果小于ma

[华为机试练习题]56.求子数组的最大和

题目 描述: 输入一个整形数组.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值. 接口 Int GetSubArraySum(Int* pIntArray,Int nCount): 规格 要求时间复杂度为O(n) 举例 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18 练习阶段: 初级 代码 /*-------------------------------

求子数组的最大和要求O(n)

//求子数组的最大和 //输入一个整形数组.有整数也有负数,数组中连续一个或多个子数组,每一个子数组都有一个和,求全部子数组的和的最大值,要求时间复杂度O(n) #include<iostream> int GetMax( int * arr) { int max = arr[0]; for (int i = 1; i < 10; i++) { if (max < arr[i]) { max = arr[i]; } } return max; } int getMaxSum(int

Java实现:求子数组的最大和(数组)

求子数组的最大和(数组) 题目: 输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为 O(n). 例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,因此输出为该子数组的和 18. 解题思路: 我觉得用户关心的的数据有两个,一个是子数组的和,还有一个是子数组具体有哪些元素,所以我们可以封装一个子数组类SubArray,成员有子数据开

算法 - 求子数组的最大和(C++)

//**************************************************************************************************** // // 求子数组的最大和 - C++ - by Chimomo // // 题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. // 求所有子数组的和的最大值.要求时间复杂度为O(n). // 例如输入的数组为5, -22, 13

C语言强化(三)发现潜在规律——求子数组的最大和

上一篇解答了在栈里面求最小值元素的问题,这一篇,来聊聊怎么找到数组中子数组的最大和. 通过这道题,你可以掌握 如何根据用户输入创建数组 如何在一连串数字中找到和最大的某一段连续数字子串 如何发现问题的潜在规律并利用这个规律设计算法,解决问题 思路 连续数相加要最大,说明左右两边的数肯定不是负数,否则不可能最大 连续数序列中允许存在负数,前提是负数前面的一段正数相加要大于这个负数,否则两者抵消后,和会变小 算法 遍历数组 遇到正数,不断累加,遇到的第一个正数要记录下标 遇到负数,记录下标,把此下标

求子数组的最大和

输入一个整形数组.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值. 接口 Int GetSubArraySum(Int* pIntArray,Int nCount): 规格 要求时间复杂度为O(n) 举例 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18 华为OJ上的这道题目与算法导论中最大子序列求和略微不同,在这里没有规定如果数组全为负数的话那么我们就定义

求子数组的最大和 【微软面试100题 第三题】

题目要求: 输入一个整型数组,数组里有整数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有个一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 例如:输入的数组为1,-2,3,10,-4,7,2,-5,和最大的子数组为3,10,-4,7,2,因此输出为该子数组的和18. 参考资料:剑指offer第31题.编程之美2.14. 题目分析: 依次读入数组值,采用两个临时变量 maxSum:保存当前数组元素之前的子数组的最大值: maxEndingHere:包含当前元素前一