代码改变世界

编程之美2.14学习笔记

2011-07-31 20:17  MichaelYin  阅读(335)  评论(0编辑  收藏  举报

再看编程之美2.14的时候发现了一个书上没有讲到的思路,就在此记录一下,也希望能给读者扩宽一下思路。

2.14的问题非常简单,就是给定一个数组,求这个数组的最大子数组之和。

书上的解法我就不赘述了,在这里主要讲一下我想到的思路。子数组之和最大,肯定有一个开始的元素,和一个结束的元素,特殊一点的话,两个是一个元素,这种特殊情况下最大子数组其实就是一个数了。然后最大从数组第一个数开始我们求和,从第一个元素到第N个元素,我们可以建立一个数组专门来存储这个求出来的和,而求出的和的右边到左边差距最大的情况的时候,我们就可以根据此得出最大子数组的和。

在遍历的过程中,我们需要定义一个变量来存储算出来的最小的和,因为我们想加的和与最小的和的差值才有可能求出最大的子数组的和。比如我们已经有了一个最小的和minSum,如果遍历过程中遇到了比这小的,那么我们就需要把这个进行替换。对于初始化的情况,我们的最小的和应该是为0,这样就把每个数字都包含进来了。

程序运行的时候是从里面已经存在了一个元素开始的。这里需要注意的是minSum的处理,如果第一个元素是小于零的话相当于第一个sumOfArray求出的是小于0的,那么我们就需要把minSum换成这个小于0的数字。然后开始遍历操作。

遍历过程中总是将求出的和与minSum进行比较,如果能大于最大的那个差值则进行替换,最后返回的就是我们需要求出的子数组之和的最大值。

下面贴出我用Java实现的代码

	public static int Test1(int[] array) {
		int sumOfArray = array[0];
		int min = (array[0] < 0) ? array[0] : 0;
		int max = array[0];
		for (int i = 1; i < array.length; i++) {
			sumOfArray += array[i];
			if (sumOfArray < min) {
				min = sumOfArray;
			} else {
				if (sumOfArray - min > max)
					max = sumOfArray - min;
			}
		}
		return max;
	}

另外关于2.14的扩展问题一也想在这里提一下,书上给出的思路貌似有点问题,我现在把我整理的思路提出来。首先求出没有同时经过首尾的最大和,这个可以用上面提到的方法做,然后我们需要求出经过首尾的最大和,但是可以看到全部节点的和是一个定值,这个问题其实可以转换为求出一个没有同时经过首尾的最小和,求出来以后用总数减去求出的最小值,然后拿这个值跟没有经过首尾的最大和进行比较,这样就能正确的求出结果。而这两个问题其实十分类似,所以其实可以放到一个for循环中完成,具体的代码这里就不写了。