【剑指Offer学习】【面试题31:连续子数组的最大和】
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求全部子数组的和的最大值。要求时间复杂度为O(n)。
样例说明:
比如输入的数组为{1, -2, 3, 10, -4, 7, 2, -5}。和最大的子数组为{3, 10, -4, 7, 2}。因此输出为该子数组的和18 。
解题思路:
解法一:举例分析数组的规律。
我们试着从头到尾逐个累加演示样例数组中的每一个数字。
初始化和为0。第一步加上第一个数字1。 此时和为1。
接下来第二步加上数字-2,和就变成了-1。第三步刷上数字3。我们注意到因为此前累计的和是-1 ,小于0,那假设用-1 加上3 ,得到的和是2 。 比3 本身还小。也就是说从第一个数字開始的子数组的和会小于从第三个数字開始的子数组的和。
因此我们不用考虑从第一个数字開始的子数组,之前累计的和也被抛弃。
我们从第三个数字又一次開始累加,此时得到的和是3 。
接下来第四步加10,得到和为13 。第五步加上-4, 和为9。我们发现因为-4 是一个负数,因此累加-4 之后得到的和比原来的和还要小。因此我们要把之前得到的和13 保存下来。它有可能是最大的子数组的和。第六步加上数字.7。9 加7 的结果是16。此时和比之前最大的和13 还要大, 把最大的子数组的和由13更新为16。第七步加上2,累加得到的和为18。同一时候我们也要更新最大子数组的和。
第八步加上最后一个数字-5,因为得到的和为13 ,小于此前最大的和18,因此终于最大的子数组的和为18 。相应的子数组是{3, 10, -4, 7, 2}。
解法二: 应用动态归划法。
能够用动态规划的思想来分析这个问题。假设用函数f(i)表示以第i个数字结尾的子数组的最大和。那么我们须要求出max[f(i)],当中0 <= i < n。我们可用例如以下边归公式求f(i):
这个公式的意义:当以第i-1 个数字结尾的子数组中全部数字的和小于0时。假设把这个负数与第i个数累加。得到的结果比第i个数字本身还要小,所以这样的情况下以第i个数字结尾的子数组就是第i个数字本身。假设以第i-1 个数字结尾的子数组中全部数字的和大于0 ,与第i 个数字累加就得到以第i个数字结尾的子数组中全部数字的和。
本题採用第一种实现方式
代码实现:
public class Test31 {
/**
* 题目2 输入一个整型数组,数组里有正数也有负数。数组中一个或连
* 续的多个整数组成一个子数组。求全部子数组的和的最大值。
要求时间复杂度为O(n)。
*
* @param arr 输入数组
* @return 最大的连续子数组和
*/
public static int findGreatestSumOfSubArray(int[] arr) {
// 參数校验
if (arr == null || arr.length < 1) {
throw new IllegalArgumentException("Array must contain an element");
}
// 记录最大的子数组和,開始时是最小的整数
int max = Integer.MIN_VALUE;
// 当前的和
int curMax = 0;
// 数组遍历
for (int i : arr) {
// 假设当前和小于等于0,就又一次设置当前和
if (curMax <= 0) {
curMax = i;
}
// 假设当前和大于0,累加当前和
else {
curMax += i;
}
// 更新记录到的最在的子数组和
if (max < curMax) {
max = curMax;
}
}
return max;
}
public static void main(String[] args) {
int[] data = {1, -2, 3, 10, -4, 7, 2, -5};
int[] data2 = {-2, -8, -1, -5, -9};
int[] data3 = {2, 8, 1, 5, 9};
System.out.println(findGreatestSumOfSubArray(data));
System.out.println(findGreatestSumOfSubArray(data2));
System.out.println(findGreatestSumOfSubArray(data3));
}
}
执行结果:
最新文章
- jquery手写实现单页滚动导航
- UDP传输
- Spring+SpringMVC+Mybatis大整合(SpringMVC采用REST风格、mybatis采用Mapper代理)
- GridFS图片
- Java 延时常见的几种方法
- WINCE设备开机灰屏问题(很怪异)
- css笔记——区分css3中的transform transition animation
- [转]How to: Execute Oracle Stored Procedures Returning RefCursors
- [Locked] Meeting Room I &;&; II
- openwrt上wifi探针的实现
- 要熟悉QT的所有类和元类系统,当然还有qmake
- 设计一个有getMin功能的栈(2)
- PHP系统左侧菜单栏的管理与实现
- 网络基础tcp/ip协议一
- JDK1.8源码(三)——java.util.HashMap
- Swift Defer 延迟调用
- HTML5-CSS3-JavaScript(1)
- vue-3-Class 与 Style 绑定
- Extjs DateTime 日期时间选择控件 (非点击日期强制选择) 支持4.0以上
- mysql批量修改列类型-生成语句