最大子序列

最大自序列求解

 

  最大自序列几乎是所有算法书籍比然要提及的一个问题,主要是因为该问题的求解方式多,而且各种算法的性能差异比较大,对程序思维的训练有很好的效果,也是面试的时候很容易就拿出来交流的。

  一般都会提到四种算法,以下是我用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~

    

posted on 2014-04-15 22:30  里克尔奇  阅读(251)  评论(0)    收藏  举报