1589. 所有排列中的最大和
大约 3 分钟
---
1589. 所有排列中的最大和
- 标签:贪心、数组、前缀和、排序
- 难度:中等
题目链接
题目大意
描述:给定一个整数数组 和一个查询数组 ,其中 表示第 个查询覆盖 中下标 的元素。
可以任意排列 中的元素。然后计算所有查询的总和(每个查询对其覆盖范围内的元素求和,然后将所有查询的和加总)。
要求:返回在所有可能的排列中,可能获得的最大总和。结果对 取模。
说明:
- 。
- 。
- 。
示例:
- 示例 1:
输入:nums = [1,2,3,4,5], requests = [[1,3],[0,1]]
输出:19
解释:一个可行的 nums 排列为 [2,1,3,4,5],并有如下结果:
requests[0] -> nums[1] + nums[2] + nums[3] = 1 + 3 + 4 = 8
requests[1] -> nums[0] + nums[1] = 2 + 1 = 3
总和为:8 + 3 = 11。
一个总和更大的排列为 [3,5,4,2,1],并有如下结果:
requests[0] -> nums[1] + nums[2] + nums[3] = 5 + 4 + 2 = 11
requests[1] -> nums[0] + nums[1] = 3 + 5 = 8
总和为: 11 + 8 = 19,这个方案是所有排列中查询之和最大的结果。- 示例 2:
输入:nums = [1,2,3,4,5,6], requests = [[0,1]]
输出:11
解释:一个总和最大的排列为 [6,5,4,3,2,1] ,查询和为 [11]。解题思路
思路 1:差分 + 排序
1. 核心思想
每个位置 被查询覆盖的次数决定了它对总和的贡献次数。把较大的数放在被查询次数较多的位置上,总和最大。
问题转化为:
- 统计每个位置的被查询次数(使用差分数组)。
- 将次数数组降序排序, 降序排序。
- 对应位置相乘再求和。
2. 具体步骤
第 1 步:初始化差分数组 长度为 。
第 2 步:对于每个 :
- 。
- 。
第 3 步:前缀和得到每个位置的被查询次数 。
第 4 步: 降序排序, 降序排序。
第 5 步:计算 。
3. 正确性证明
- 排序不等式:两个序列 和 , 最大当且仅当 和 同序(即同升序或同降序)。
- 这里 是次数, 是数值,同序得最大和。
4. 举例说明
以 为例:
- 查询覆盖次数:
- 位置 : 次()
- 位置 : 次()
- 位置 : 次()
- 位置 : 次()
- 位置 : 次
- 次数排序:
- 排序:
- 最大和:
思路 1:代码
class Solution:
def maxSumRangeQuery(self, nums: List[int], requests: List[List[int]]) -> int:
MOD = 10 ** 9 + 7
n = len(nums)
diff = [0] * (n + 1)
for l, r in requests:
diff[l] += 1
diff[r + 1] -= 1
cnt = [0] * n
cur = 0
for i in range(n):
cur += diff[i]
cnt[i] = cur
cnt.sort(reverse=True)
nums.sort(reverse=True)
ans = 0
for i in range(n):
ans = (ans + cnt[i] * nums[i]) % MOD
return ans思路 1:复杂度分析
- 时间复杂度:,排序。
- 空间复杂度:。