官解
class Solution(object):
# 定义常量
mod = int(1e9 + 7) # 模数,用于防止结果溢出
inf = float('inf') # 无穷大,用于初始化时的特殊值
def sumOfPowers(self, nums, k):
n = len(nums) # 数组长度
res = 0 # 用于存储最终结果
# 三维动态规划表,d[i][p][v] 表示以 nums[i] 结尾的长度为 p 的子序列,最小绝对差为 v 的频次
d = [[defaultdict(int) for _ in range(k + 1)] for _ in range(n)]
nums.sort() # 对 nums 进行排序,确保子序列的顺序
for i in range(n):
# 初始化:长度为 1 的子序列,最小绝对差为无穷大,频次为 1
d[i][1][self.inf] = 1
for j in range(i):
# 计算 nums[i] 和 nums[j] 之间的绝对差
diff = abs(nums[i] - nums[j])
# 更新长度为 p 的子序列的最小绝对差,其中 p 从 2 到 k
for p in range(2, k + 1):
for v, cnt in d[j][p - 1].items():
# 更新 d[i][p][min(diff, v)]
d[i][p][min(diff, v)] = (d[i][p][min(diff, v)] + cnt) % self.mod
# 计算结果:遍历所有以 nums[i] 结尾的长度为 k 的子序列
for v, cnt in d[i][k].items():
# 累加 v * cnt 到 res 中,并取模
res = (res + v * cnt % self.mod) % self.mod
return res # 返回最终结果
Chatgpt解
这段代码实现了一个名为sumOfPowers
的方法,它的目标是计算给定数组 nums
中所有长度为 k
的子序列的最小绝对差的和,并将结果对 1e9 + 7
取模。
代码分解与解释
变量和数据结构
mod = int(1e9 + 7)
: 模数,用于防止结果溢出。inf = float('inf')
: 表示无穷大,用于初始化时的特殊值。d = [[defaultdict(int) for _ in range(k + 1)] for _ in range(n)]
: 三维动态规划表,用于存储子序列的最小绝对差。d[i][p]
表示以nums[i]
结尾的长度为p
的子序列,其最小绝对差的频次。d[i][p][v]
表示上述子序列中,最小绝对差为v
的子序列数量。
算法步骤
-
初始化:
n = len(nums)
: 数组nums
的长度。res = 0
: 用于存储最终结果。nums.sort()
: 对nums
进行排序,确保子序列的顺序。- 初始化
d[i][1][inf] = 1
,表示长度为 1 的子序列,最小绝对差为无穷大。
-
动态规划填表:
- 遍历数组的每一个元素
nums[i]
:- 对于每一个之前的元素
nums[j]
(其中j < i
):- 计算
nums[i]
和nums[j]
之间的绝对差diff
。 - 更新长度为
p
的子序列的最小绝对差,其中p
从 2 到k
:- 对于
d[j][p-1]
中的每个v
和cnt
:- 更新
d[i][p][min(diff, v)]
,其中v
是子序列的最小绝对差,cnt
是其出现的频次。 - 使用
min(diff, v)
确保当前子序列的最小绝对差。
- 更新
- 对于
- 计算
- 对于每一个之前的元素
- 遍历数组的每一个元素
-
计算结果:
- 遍历所有以
nums[i]
结尾的长度为k
的子序列:- 对于每个最小绝对差
v
和其出现的频次cnt
:- 累加
v * cnt
到res
中,并取模。
- 累加
- 对于每个最小绝对差
- 遍历所有以
返回结果
- 返回
res
,即所有长度为k
的子序列的最小绝对差的和,并对1e9 + 7
取模。
代码的关键点
- 使用三维动态规划表
d
来存储子序列信息。 - 确保子序列按照递增顺序进行计算,避免重复计算。
- 通过
min(diff, v)
保持子序列的最小绝对差。
总结
这段代码通过动态规划的方法有效地计算了所有长度为 k
的子序列的最小绝对差,并利用模数 1e9 + 7
处理可能出现的大数溢出问题。代码的核心思想是利用前缀子序列的信息来逐步构建长度为 k
的子序列,并在构建过程中不断更新最小绝对差。