剑指offer-面试题31-连续子数组的最大和

package case31_FindGreastSumOfSubArray;

import java.util.ArrayList;

/**
 * 题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(N)。
 * 
 * @author WangSai
 *
 */
public class FindGreastSumOfSubArray {

	public static void main(String[] args) {
		int[] arr = { 1, -2, 3, 10, -4, 7, 2, -5 };
		System.out.println("getMyGreatSum1(arr):  " + getMyGreatSum1(arr));
		System.out.println("getMyGreatSum2(arr):  " + getMyGreatSum2(arr));
	}

	/**
	 * 方法1:通过从数组头开始累加。
	 * 
	 * @param arr,要被处理的数组
	 * @return 最大子数组的和
	 */
	private static int getMyGreatSum1(int[] arr) {
		// 异常值检测
		if (arr == null || arr.length <= 0)
			throw new IllegalArgumentException("非法参数,请重新检查...");
		// 设置两个变量,currentSum保存当前子数组的和。maxSum保存最大的子数组的和。数组中有正数,所以,currentSum和maxSum最小值都会大于0
		int currentSum = Integer.MIN_VALUE;
		int maxSum = Integer.MIN_VALUE;
		// 分别保存最长子数组的两个角标
		int low = 0;
		int high = 0;

		for (int i = 0; i < arr.length; i++) {
			// 若arr[i]之前元素的子数组的和小于等于0,说明之前的子数组的和加上arr[i]不会 大于 从arr[i]开始算起的子数组的和。
			// 抛弃之前的子数组,从当前元素开始算起。
			// low是开始角标
			if (currentSum <= 0) {
				currentSum = arr[i];
				low = i;
			} else
				currentSum += arr[i];
			// 获取最大的子数组的和。子数组结束的角标
			if (currentSum > maxSum) {
				maxSum = currentSum;
				high = i;
			}
		}
		System.out.print("最大的子数组为:      ");
		for (int i = low; i <= high; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
		return maxSum;

	}

	/**
	 * 方法2:动态规划的方法实现
	 * 
	 * @param arr,要被处理的数组
	 * @return 最大子数组的和
	 */
	private static int getMyGreatSum2(int[] arr) {
		if (arr == null || arr.length <= 0)
			throw new IllegalArgumentException("非法参数,请重新检查...");
		ArrayList<Integer> list = new ArrayList<>();
		int currentSum = Integer.MIN_VALUE;
		int maxSum = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			if (i == 0) {
				list.add(arr[i]);
			} else if (currentSum <= 0) {
				list.add(arr[i]);
				currentSum = arr[i];
			} else if (currentSum > 0) {
				currentSum += arr[i];
				list.add(Math.max(currentSum, arr[i]));
			}
		}
		maxSum = list.get(0);
		for (int i : list) {
			if (i > maxSum)
				maxSum = i;
		}
		return maxSum;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值