最大子序列
最大自序列求解
最大自序列几乎是所有算法书籍比然要提及的一个问题,主要是因为该问题的求解方式多,而且各种算法的性能差异比较大,对程序思维的训练有很好的效果,也是面试的时候很容易就拿出来交流的。
一般都会提到四种算法,以下是我用Go语言实现的其中两种的过程:
- 递归分治,性能不是最好,但是可以很好的理解递归和分治策略
-
//第三种算法:递归,分治策略 func MaxSubSum3(aArray []int, left int, right int) (maxSum int) { //基本情况,若左右下标相等的话,取一个值返回,约定:若值小于0就返回0. if left == right { if aArray[left] > 0 { return aArray[left] } else { return 0 } } center := (left + right) / 2 //#########递归左半边############ maxLeftSum := MaxSubSum3(aArray, left, center) //#########递归右半边############ maxRightSum := MaxSubSum3(aArray, center+1, right) /*#########也有可能是即有左半边的部分和右半边的部分########### 从中间位置往左计算这部分的最大自序列(这个方向千万别反了) 计算方向 左边<------------中间位置 */ maxLeftBorderSum, leftBorderSum := 0, 0 for i := center; i >= left; i-- { leftBorderSum = aArray[i] + leftBorderSum if leftBorderSum > maxLeftBorderSum { maxLeftBorderSum = leftBorderSum } } /*#########也有可能是即有左半边的部分和右半边的部分########### 从中间位置往右计算这部分的最大自序列(这个方向与上边正好相反) 计算方向 ------------中间位置------------>右边 */ maxRightBorderSum, rightBorderSum := 0, 0 for j := center + 1; j <= right; j++ { rightBorderSum = rightBorderSum + aArray[j] if rightBorderSum > maxRightBorderSum { maxRightBorderSum = rightBorderSum } } //好了可以比较左边最大自序列值/右半边最大自序列值/横跨左右两边的情况,三者最大值返回就OK啦 tmpArray := []int{maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum} //写了个冒泡排序,在另一篇博文里面有实现,这里之前写的拿过来直接用了,实际应用时,数据量大的话,不要冒泡排序, //毕竟我们只要最大数不需要全排序 sort.BubbleSort(tmpArray) return tmpArray[len(tmpArray)-1] }
- 线性时间复杂度的算法,我是没想出来,看了书才知道...我稍微改了以下,把最大自序列的开始和结束下标也返回。
-
func MaxSubSum4(aArray []int) (maxSum, begin, end int) { thisSum := 0 for index, value := range aArray { thisSum = thisSum + value fmt.Println("thissum:", thisSum) if thisSum > maxSum { maxSum = thisSum
//如果当前和大雨最大和就更新一下end值 end = index } else if thisSum < 0 { thisSum = 0
//如果当前和小于0,将向下推进
begin = index + 1 } } return maxSum, begin, end }done~
浙公网安备 33010602011771号