算法题:最大单调不减不增子序列和

问题描述:

给出一个由 n 个数组成的数组,n 不超过 5*10^5,你需要创建一个新数组,长度也为 n,且每一格上的数都小于等于原数组同一格子上的数,新数组必须是先单调不减,再单调不增的,在符合条件的新数组里,n 个元素的和要尽量的大,问这个和的最大值。

样例输入:

6
1 1 4 5 1 4

样例输出:

13

思路:

先从左往右扫描一遍数组,保证新数组单调不减;再从右往左扫描一遍数组,保证新数组单调不增。这样得到的新数组必定是符合条件的,且和最大。具体实现时,可以使用两个单调栈,一个从左往右维护单调不减的子序列,另一个从右往左维护单调不增的子序列。时间复杂度为 O(n)。

Python 代码:

def max_sum_subsequence(nums):
    n = len(nums)
    increasing_stack = []  # 单调不减栈
    decreasing_stack = []  # 单调不增栈
    result = [0] * n

    # 从左往右扫描,维护单调不减子序列
    for i in range(n):
        if not increasing_stack or nums[i] >= increasing_stack[-1]:
            increasing_stack.append(nums[i])
        else:
            j = len(increasing_stack) - 1
            while j >= 0 and nums[i] < increasing_stack[j]:
                j -= 1
            increasing_stack[j + 1] = nums[i]

    # 从右往左扫描,维护单调不增子序列
    for i in range(n - 1, -1, -1):
        if not decreasing_stack or nums[i] <= decreasing_stack[-1]:
            decreasing_stack.append(nums[i])
        else:
            j = len(decreasing_stack) - 1
            while j >= 0 and nums[i] > decreasing_stack[j]:
                j -= 1
            decreasing_stack[j + 1] = nums[i]

    # 合并两个栈,得到最终结果
    i = 0
    j = 0
    k = 0
    while i < len(increasing_stack) and j < len(decreasing_stack):
        if increasing_stack[i] <= decreasing_stack[j]:
            result[k] = increasing_stack[i]
            i += 1
        else:
            result[k] = decreasing_stack[j]
            j += 1
        k += 1

    # 处理剩余元素
    while i < len(increasing_stack):
        result[k] = increasing_stack[i]
        i += 1
        k += 1
    while j < len(decreasing_stack):
        result[k] = decreasing_stack[j]
        j += 1
        k += 1

    return sum(result)

nums = [1, 1, 4, 5, 1, 4]
max_sum = max_sum_subsequence(nums)
print(max_sum)  # 输出 13
算法题:最大单调不减不增子序列和

原文地址: https://www.cveoy.top/t/topic/nMTG 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录