30.连续子数组的最大和
来源:互联网 发布:htpc专用软件 编辑:程序博客网 时间:2024/06/05 21:44
一、题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)
二、思路
首先,我们会想到用两个数来辅助存储当前的最大和,定义两个变量res和sum,res用来记录当前的最大和,sum用来记录当前的和,如果sum大于res,则更新res。这一步想好之后,接下来就是遍历数组,我们最容易想到的就是使用双层循环来遍历数组,以便找到从任意位置开始的连续子数组的最大和,但是,如果仔细想想,其实,我们只对数组遍历一次,也是能够找到连续子数组的最大和的,下面是两种方法的代码实现。
方法一:使用双层循环,时间复杂度O(n^2)
public class Solution { public int FindGreatestSumOfSubArray(int[] array) { int res = array[0]; for (int i = 0; i < array.length; i++){ int sum = 0; for (int j = i; j < array.length; j++){ sum += array[j]; if (sum > res) res = sum; } } return res; }}
方法二:单层循环,在方法一中,如果数组第i个元素为负数,那么我们其实是没有必要进行i元素以后的遍历的,因为,负数总会让和变小,既然要变小,我们为什么还要这一次遍历呢?所以就有下面的改进方法。
/***改进版,遍历一次数组即可,时间复杂度O(n)。*用两个变量来进行记录,一个用于加和,一个用于记录最大和。**/public class Solution { public int FindGreatestSumOfSubArray(int[] array) { if (array.length == 0 || array == null) return 0; int res = array[0]; int sum = 0; for (int i = 0; i < array.length; i++){ if (sum < 0){ sum = array[i];//因为加一个负数肯定会使结果小于array[i],所以直接舍去负数 } else { sum += array[i]; } if (sum > res) res = sum; } return res; }}
该题目的变形:求使出现最大和的子数组;
思路:用两个标签分别记录子数组开始和结束的位置,如果使用for双层循环的话,当出现新的最大值时,分别记录i和j的值,下面是另一种循环求解:
/* * 1.找出出现最大连续和的子数组 * 当数组有正有负时,i=0遍历数组,从大于0的那个元素开始,记录此时的下标为shart(最大子数组起始下标),从start开始遍历剩下的元素,若元素和num大于max的值则更新max, * 且将此时的下标赋值给end(最大子数组终止下标),当num小于0则说明后面出现的(如果出现)最大子数组不可能包含这些元素,所以退出内层循环,继续外层循环,找下一个大于 * 0的数组元素,且外层循环的i变量此时变为temp+1,继续下面的循环。注意内层循环当temp>=length时,说明内层循环已经把所有数组元素都遍历结束,所以外层循环可以直接break。 */ public static ArrayList<Integer> findGreatestSumArrayOfSubArray(int arr[]) { ArrayList<Integer> list = new ArrayList<Integer>(); int i = 0; int temp = 0; int num = 0; int max = 0; int start = 0; int end = 0; int flag = 0;//用来判断数组中是否全为负,如果flag = arr.length,则全为负数 while (i < arr.length){ //第一层循环,从大于零的元素位置开始,并记录开始下标, if (arr[i] > 0){ temp = i; start = i; while (temp < arr.length){ //第二层循环,用temp做临时变量,找最大值,并记录最大值结束下标 num += arr[temp]; if (num < 0){ num = 0; i = temp + 1; break; } if (num > max){ max = num; end = temp; } temp++; } if(temp >= arr.length) //避免在外层循环中陷入死循环,因为此时i不一定等于数组长度,i值不增,外层循环则停不下来。 break; } else { i++; flag++; } } if (flag == arr.length) //如果元素全为负,则输出空数组 return list; else { for (int j = start; j<= end; j++) list.add(arr[j]); } return list; }
0 0
- 30.连续子数组的最大和
- 数组连续子数组的和最大
- 数组连续子数组的最大和
- 连续子数组的最大和
- 连续子数组的最大和
- 连续子数组的最大和
- 求连续子数组的最大和
- 连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 连续子数组的最大和
- 连续子数组的最大和
- (8)连续子数组的最大和
- 求连续子数组的最大和
- 求连续子数组的最大和
- 连续子数组的最大和
- 求连续子数组的最大和
- 连续子数组的最大和
- 机器学习1—入门
- 【深入剖析Tomcat笔记】第一篇 基础知识储备
- ReactRouter 离开页面的钩子
- iOS之CALayer与核心动画(四)
- Laravel5.3 使用默认api验证登陆
- 30.连续子数组的最大和
- Leetcode Decode Ways
- Thread的run()与start()的区别
- 密码学之二(自签名证书解析)
- Mongodb常用操作语句
- get_user;put_user;copy_to_user;copy_from_user
- Spring自定义标签
- Ubuntu 16.04 安装 wine
- 破解navicat11