作为零基础学习的弱智艰难的入行后,在黑暗中摸爬滚打中过了几个月,才想起应该开个博客记录下自己的学习历程和整理知识点。刚刚接触算法的我,博客就以记录我的算法学习历程为开端吧。多说无益,下面开始:
如果已知后三十天的股票涨跌停的情况,那么我该如何确定自己收益的最大值是多少呢?这里可以将股票每天的变化存进一个数组里,涨记为正,跌记为负,那么最后这个实际问题就转化为了求最大连续子数组的问题了,即我怎么切割这个数组使得这个数组里的值最大?这里简单的用了分治法去计算,首先将data分成2份,一份为左data,一份为右data,那么就可以通过循环求出左右data各自的最大值,先求左边数组(以下为python代码)
#left array mid = len(data)/2 ssum = 0 sumLeft = 0 leftData = data[:mid] leftIndex = 0 for i in range(len(leftData)-1,-1,-1): ssum = ssum + leftData[i] if ssum > sumLeft: sumLeft = ssum leftIndex = i
mid为data的中点,用mid把data分成2份,左边数组为leftData,利用ssum计算左数组中的累加值,leftData存累加的最大值。如果累加值大于了最大值,那么就把这个累加值存为最大值。右边数组同理
#right array sumRight = 0 ssum = 0 rightData = data[mid:] rightIndex = 0 for j in range(len(rightData)): ssum = ssum +rightData[j] if ssum > sumRight: sumRight = ssum rightIndex = j
这样就能算出左右2边的最大连续子数组啦,是不是相互比较之后返回较大那个就Ok了呢?没有,原来忽略了一个,就是假如这个最大子数组跨过了中点mid呢?我们还得把这个数组的最大子数组取出来一起比较:
crossData = data[leftIndex:rightIndex + mid + 1] sumCross = 0 ssum = 0 crossIndex = 0 for x in range(len(crossData)): ssum = ssum + crossData[x] if ssum > sumCross: sumCross = ssum crossIndex = x
之前用i,j 分别记录了左数组的最大值索引i,和右数组的最大值索引j,那么可以想到这个cross数组必然在i,j这2个边界内,因为这2个已经是2边的最大值了,如果再加超出边界部分的值一定是小于最大值的。
所以可以把data切割为crossData,这里要注意j因为是右边数组,所以j在整个data中应该还需要加上中点的值才能真正获取到crossData的右边界,因为切割的时候不包含最后的j,为了把右边界算进去,还必须加上1
之后按照之前的套路,求出crossData的最大值 sumCross
好了,接下来这3个值进行比较返回最大的就可以了
maxSum = max(sumRight,sumLeft,sumCross)
由于刚学,算法还有很多可以改进的地方,只能一步一步来了。