• [算法] 求解和值最大子段及绝对值最小子段


    求和值最大子段:不断对已有子段加值,当和值小于0时舍弃子段;由遍历决定复杂度O(n);

    求和值绝对值最小子段:求前n子段和值,然后求最小差值;求最小差值时使用了排序后遍历的方法,由排序决定复杂度O(nlogn);这里求最小差值的问题中,在某些限制条件下(数组波动不大)可以用桶排序进一步降低时间复杂度,见求最小差值,但因有条件限制不稳定,故不选取;

    # -*- coding: utf-8 -*-
    
    array = (4, -3, 2, 5, -9, 6)
    #array = (4, -3, 1)
    #array = (-4, -3, -2, -5, -9, -6)
     
    # 求解和值最大子段
    # 算法关键是将和值对整体不利的子序列舍弃,修减问题树
    # 复杂度O(n)
    def big_sub():
        try_sum = 0
        try_start = 0
     
        start = 0
        end = 0
        sum = 0
        big = array[0]
        big_index = 0
     
        for i in range(0, len(array)):
     
            if try_sum >= 0:
                try_sum += array[i]
                if (try_sum > sum):
                    sum = try_sum
                    end = i
                    start = try_start
            else: # try_sum < 0
                try_sum = array[i]
                try_start = i
     
            if array[i] > big:
                big = array[i]
                big_index = i
     
        if sum == 0:
            sum = big
            start = end = big_index
     
        print array[start:end+1],
        print sum
     
    # 求解和值绝对值最小子段
    # 算法关键是求解前n子段和后进行排序,找数列最小差值
    # 因为有排序过程存在,所以时间复杂度达到O(nlogn)
     
    # 快排
    def split(tuples, start, end):
        middle = tuples[end]
        index = start-1
        for i in range(start, end+1):
            if tuples[i][1] <= middle[1]:
                index += 1
                temp = tuples[index]
                tuples[index] = tuples[i]
                tuples[i] = temp
        return index
     
    def sort_tuples(tuples, start, end):
        if start < end:
            index = split(tuples, start, end)
            sort_tuples(tuples, start, index-1)
            sort_tuples(tuples, index+1, end)
     
    def small_sub():
        sum = 0
        sums = []
        for i in range(0, len(array)):
            sum += array[i]
            sums.append((i, sum))
     
        # 排序
        sort_tuples(sums, 0, len(sums)-1)
     
        # 找最小差值
        small_diff = -1
        small_diff_index = 0
        for i in range(0, len(array)-1):
            diff = sums[i+1][1] - sums[i][1]
     
            if (small_diff < 0) or (diff < small_diff):
                small_diff = diff
                small_diff_index = i
     
        if (sums[small_diff_index][0] < sums[small_diff_index+1][0]):
            start = sums[small_diff_index][0]
            end = sums[small_diff_index+1][0]
            minus = False
        else:
            end = sums[small_diff_index][0]
            start = sums[small_diff_index+1][0]
            minus = True
     
        print array[start+1:end+1],
        if minus:
            print -small_diff
        else:
            print small_diff
     
    if __name__ == "__main__":
        big_sub()
        small_sub()
    

     

    注:为处理全负数组,在求最大和子段时,用了一个空间big保存最大元素值;

  • 相关阅读:
    linux ipsec
    inotify+rsync
    多实例tomcat
    Http和Nginx反代至Tomcat(LNMT、LAMT)
    cisco ipsec
    ansible基础
    Qt 汉字乱码
    Model/View
    面对焦虑
    QT中QWidget、QDialog及QMainWindow的区别
  • 原文地址:https://www.cnblogs.com/ZisZ/p/3301977.html
Copyright © 2020-2023  润新知