返回

子数组最大累加和巧解、最长回文子串优雅处理

Android

引言

子数组最大累加和和最长回文子串,这两大经典算法问题在计算机科学领域中扮演着重要角色。前者用于解决一维数组中最大连续子数组和的问题,后者用于寻找字符串中的最长回文子串。今天,我们将在本文中探讨巧妙高效的解决方案,助您攻克这两个难题。

NC19 子数组的最大累加和问题

问题

给定一个数组,求出其所有子数组中最大累加和。

算法思想

子数组最大累加和问题的经典解法是动态规划 。我们定义状态dp[i]表示以第i个元素结尾的子数组的最大累加和。那么状态转移方程为:

dp[i] = max(dp[i-1] + nums[i], nums[i])

其中nums为输入数组。

时间复杂度:O(n) ,其中n为数组长度。

代码实现

def max_subarray_sum(nums):
    dp = [0] * len(nums)
    dp[0] = nums[0]
    for i in range(1, len(nums)):
        dp[i] = max(dp[i-1] + nums[i], nums[i])
    return max(dp)

NC17 最长回文子串

问题

给定一个字符串,求出其最长的回文子串。

算法思想

最长回文子串问题的经典解法是Manacher算法 。该算法利用一个处理过的字符串来巧妙地处理回文子串问题。我们定义一个新的字符串s,将原字符串t中的每个字符插入到s中,并在每个字符之间插入一个分隔符(例如#)。

时间复杂度:O(n) ,其中n为原字符串长度。

代码实现

def longest_palindrome(s):
    # 构建处理过的字符串
    t = "#" + "#".join(s) + "#"

    # 回文半径数组
    p = [0] * len(t)

    # 中心和右边界
    center = right = 0

    # 最长回文子串长度和起始位置
    max_len = 0
    start = 0

    for i in range(1, len(t)):
        # 计算当前位置的回文半径
        mirror = 2 * center - i
        if i < right:
            p[i] = min(right - i, p[mirror])
        
        # 扩展回文半径
        while i - p[i] - 1 >= 0 and i + p[i] + 1 < len(t) and t[i - p[i] - 1] == t[i + p[i] + 1]:
            p[i] += 1
        
        # 更新中心和右边界
        if i + p[i] > right:
            center = i
            right = i + p[i]
        
        # 更新最长回文子串信息
        if p[i] > max_len:
            max_len = p[i]
            start = (i - max_len) // 2

    return s[start:start+max_len]

结语

子数组最大累加和和最长回文子串,这两大算法问题在实际应用中有着广泛的应用场景。通过巧妙高效的算法,我们可以轻松解决这些难题,为计算机科学的进步添砖加瓦。