返回

异想天开的间隔求和之探险:解密周赛 273 5965

后端

算法周赛 273:揭开间隔之和的面纱

引言

欢迎来到算法周赛 273 的盛宴,我们即将开启一段破译谜题的旅程,探索一道貌似简单却暗藏玄机的题目:5965. 相同元素的间隔之和。

灵感的萌芽:字典中的线索

比赛伊始,脑海一片空白,时间一分一秒地流逝,焦灼感与希望交织。突然,一道灵光划过,宛如黑夜中的流星,照亮了前进的方向:相同数字的下标,可以用字典来记录!字典的键是数字,值是该数字在数组中的下标列表。

动态规划的舞台:逐一计算间隔之和

有了字典的助力,我们踏入了动态规划的舞台。dp[i][j] 表示从数组第一个元素到下标为 i 的子数组中,以 j 为结尾的相同元素间隔之和。转移方程应运而生:

dp[i][j] = dp[i - 1][j] + (nums[i] == nums[j] ? i - prev[nums[i]] : 0);

其中,prev[nums[i]] 表示数字 nums[i] 上一次出现的位置。

代码的舞步:用 Python 诠释算法

将算法转化为代码,我们有:

def getSumAbsoluteDifferences(nums):
    prev = {}  # 记录每个元素上一次出现的位置
    n = len(nums)
    dp = [[0] * n for _ in range(n)]  # 动态规划表

    for i in range(n):
        for j in range(i):
            if nums[i] == nums[j]:
                dp[i][j] = dp[i - 1][j] + (i - prev[nums[i]])
            else:
                dp[i][j] = dp[i - 1][j]
        prev[nums[i]] = i

    return dp[n - 1][n - 1]

实例的验证:以数字揭秘答案

让我们用一个实例来检验我们的算法。给定数组 nums = [4, 2, 1, 4, 8] ,它的相同元素间隔之和是多少呢?

字典 prev:{4: 0, 2: 1, 1: 2, 8: 4}
动态规划表 dp:
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0],
 [0, 0, 0, 1, 2]]

最终结果:dp[4][4] = 2

结论:算法之美,解谜之乐

周赛 273 的 5965 题是一场思维与技术的较量。我们巧妙地利用字典记录相同元素的下标,再借助动态规划计算间隔之和。从灵感的火花到代码的舞步,我们一步步揭开了这道题目的面纱。算法的魅力就在于此,它带领我们踏上探索未知,发现规律的奇妙旅程。

常见问题解答

  1. 什么是动态规划?
    动态规划是一种优化问题的技术,它将问题分解为子问题,并通过逐一解决子问题来获得最终结果。

  2. 为什么使用字典来记录相同元素的下标?
    字典可以快速查找相同元素的上一次出现位置,这对于计算间隔之和至关重要。

  3. 转移方程的含义是什么?
    转移方程计算当前子问题的间隔之和,它等于前一个子问题的间隔之和,如果当前元素与上一个相同元素相同,则加上当前元素和上一个相同元素下标之差。

  4. 算法的时间复杂度是多少?
    算法的时间复杂度为 O(N²),其中 N 是数组的长度。

  5. 算法的空间复杂度是多少?
    算法的空间复杂度为 O(N),因为我们需要存储字典和动态规划表。