从一道easy leetcode问题,谈谈最大子列和的Kadane算法

来源:互联网 发布:软件过试用期 编辑:程序博客网 时间:2024/05/20 07:19

发现网上讲解kadane算法的文档都是英文的,于是自己就拿中文总结一下,希望能对大家有所帮助。

最大子列和问题是算法中的经典问题。记得一年前刚学数据结构时,还总结过一篇求最大子列和算法的博客。博文地址:最大子列和的四种算法比较

昨天无事刷leetcode,被一道easy的题目难住,121. Best Time to Buy and Sell Stock。拿java写了三十多行代码,最后还是计算错误。无奈之下只能看答案,也算是机缘巧合,在排名第一的答案中,接触到了计算最大子列和的kadane算法,优雅至极,完爆我上面那篇博文中的所有算法,惊呼genius。于是在这里总结一下算法的思想,寄托一下我佩服的五体投地的感情。

先简要介绍题目。题目是说,给你一个股票每日的价格表,这个价格表用一个数组来表示。在只买卖一次的情况下,求最大收益。

这道问题的第一个巧妙之处在于,可以把它转化为一个求最大子列和的问题(原谅我智商捉急,这点也没想到)。对于原数组,如果我们将arr[i]-arr[i-1],也就是股票某日与前一日价格差,依次排列成一个数组,那么所求问题的答案就变成了求这个新数组的最大子列和。

于是,这道题的第二个巧妙之处,也就是在求解最大子列和问题时,使用了kadane算法。算法复杂度O(N),同我上篇博文中最后一个算法的复杂度相同,但优雅程度完爆之。

kadane算法利用了数学归纳法的思想。简单来讲就是,随意给你一个现成的数组,比如说−2, 1, −3, 4, −1, 2, 1, −5, 4,让你求其中的最大子列和,并不是容易的事情。但如果我们能从第一个数开始,随着数组的扩充,始终对其最大子列和保持跟踪,就可以轻易的求出任意一个数组的最大子列和。换言之,长度n的数组我们不会求,长度为一的总能算出来吧?长度为一的算出来了,二也就能算出来,二算出来了,三就能算出来,以此类推,用这种根据i求i+1的思想,我们就能达到最终目的。

详细的分析一下,往一个长度为i的数组后面插入第i+1个数,这时,数组的最大子列只有两种情况,要么包括第i+1个数,要么不包括第i+1个数。即:

maxsubarraum = max(以第i+1个数结尾的子列和, 不以第i+1个数结尾的子列和)。*

先计算前者,以第i+1个数结尾的子列和怎么算呢?很简单,要么它是以第i个数结尾的子列作为前缀,要么它不以之作为前缀。假设第i+1个数为x,那么:

以第i+1个数结尾的子列和 = max(x,以第i个数结尾的子列和+x)。(1)

再计算后者,也就是不以第i+1个数结尾的子列和。这啥意思呢?其实就是插入第i+1个数之前的数组的最大子列和嘛。我们的数学归纳思想也就体现在这里,如果你还看不明白,我们将*式改写:

数列长度i+1的最大子列和 = max(以第i+1个数结尾的子列和, 数列长度i的最大子列和)。(2)

看到了吧,无论一式还是二式,后一种情况都可以由前一种情况推出,妥妥的数学归纳。我们的算法只要从i=1开始,一步一步按照上面的规则走下去,那么任意一个数列的最大子列和就能求出来了!

代码写下来,以供参考:

public int max_subarray(int[] A){ max_ending_here = max_so_far = A[0]; for(int n = 1; n < A.length; n++){  max_ending_here = Math.max(max_ending_here + A[n], A[n]);  max_so_far = Math.max(max_ending_here, max_so_far);  } return max_so_far;}

顺便把这道leetcode 的easy 问题的答案也写上来吧,用了kadane算法,代码精准而优雅,啧啧啧。。。

public class Solution {    public int maxProfit(int[] prices) {        int max_ending_here, max_so_far;        max_ending_here = max_so_far =0;        for(int n = 1; n < prices.length; n++){            max_ending_here = Math.max(max_ending_here + prices[n] - prices[n-1], prices[n] - prices[n-1]);            max_so_far = Math.max(max_ending_here, max_so_far);        }        return max_so_far;        }    }

相关资料链接:
Maximum subarray problem

原创粉丝点击