arrays - 使数组的对和相等的最小操作数
问题描述
你会得到一个偶数长度的整数列表。考虑一个操作,您可以在 nums 中选择任意数字并使用 [1, max(nums)] 之间的值对其进行更新。返回所需的操作数,使得对于每个 i,nums[i] + nums[n - 1 - i] 等于相同的数字。这个问题可以贪婪地解决。
注意:n 是数组的大小,max(nums) 是 nums 中的最大元素。
例如:nums = [1,5,4,5,9,3] 预期的操作是 2。
解释: maxnums 是 9,所以我可以将 nums 的任何元素更改为 [1, 9] 之间的任何数字,这需要一次操作。
- 在索引 0 处选择 1 并将其更改为 6
- 在索引 4 处选择 9 并将其更改为 4。
现在这使得 nums[0] + nums[5] = nums[1] + nums[4] = nums[2] + nums[3] = 9。我们改变了 2 个数字,它花费了我们 2 次操作,这是此输入的最小值。
我使用的方法是找到总和的中位数并用它来贪婪地找到操作的数量。让我们根据给定条件找到数组的所有和。
总和可以通过 nums[i] + nums[n-1-i] 计算。
令 i = 0,nums[0] + nums[6-1-0] = 4。
i = 1,nums[1] + nums[6-1-1] = 14。
i = 2,数字 [2] + 数字 [6-1-2] = 9。
将这些总和存储在一个数组中并对其进行排序。sums = [4,9,14] 排序后。现在从总和中找到中位数,即 9,因为它是中间元素。
现在我使用这个中位数来平衡总和,我们可以找到操作的数量。我还添加了用于计算操作次数的代码。
int operations = 0;
for(int i=0; i<nums.size()/2; i++) {
if(nums[i] + nums[nums.size()-1-i] == mid)
continue;
if(nums[i] + nums[nums.size()-1-i] > mid) {
if(nums[i] + 1 <= mid || 1 + nums[nums.size()-1-i] <= mid) {
operations++;
} else {
operations += 2;
}
} else if (maxnums + nums[nums.size()-1-i] >= mid || nums[i] + maxnums >= mid) {
operations++;
} else {
operations += 2;
}
}
此示例的总操作数为 2,这是正确的。
这里的问题是,对于某些情况,选择中位数会给出错误的结果。例如,nums = [10, 7, 2, 9, 4, 1, 7, 3, 10, 8] 需要 5 次操作,但如果选择中位数 (16),我的代码会给出 6。
选择中位数不是最佳方法吗?任何人都可以帮助提供更好的方法吗?
解决方案
我认为以下应该有效:
- 迭代数对
- 对于每一对,计算该对的总和,以及通过仅更改其中一个值可以实现的最小和最大总和
- 当开始一个需要较少更改的新“区域”时使用 -1 更新字典/地图,当该区域结束时使用 +1
- 迭代该字典中的边界并更新所需的总更改以找到需要最少更新的总和
Python 中的示例代码,9
作为您的示例的最佳总和,需要5
更改。
from collections import defaultdict
nums = [10, 7, 2, 9, 4, 1, 7, 3, 10, 8]
m = max(nums)
pairs = [(nums[i], nums[-1-i]) for i in range(len(nums)//2)]
print(pairs)
score = defaultdict(int)
for a, b in map(sorted, pairs):
low = a + 1
high = m + b
score[low] -= 1
score[a+b] -= 1
score[a+b+1] += 1
score[high+1] += 1
print(sorted(score.items()))
cur = best = len(nums)
num = None
for i in sorted(score):
cur += score[i]
print(i, cur)
if cur < best:
best, num = cur, i
print(best, num)
总复杂度应该是 O(nlogn),创建字典需要 O(n),排序需要 O(nlogn),迭代字典中的排序值需要 O(n)。(不要使用数组,否则复杂性可能会更高max(nums) >> len(nums)
)
推荐阅读
- ios - 应用程序在 Xcode 模拟器中显示加密数据,但在 TestFlight 中不显示
- ios - 如何快速获得这个周末的约会?
- java - 如何使用 .so 文件 linux 打包所有需要的库
- php - 如何在codeigniter的动态菜单中设置树视图
- wordpress - 无法按照我想要的方式编辑英雄小部件
- jquery - 如何显示使用 jQuery 添加/删除字段添加的字段数?
- android - 从右到左增加视图宽度
- swift - 字典映射认为 String 是 String Array
- java - 测试基于注解的 RequestInterceptor
- react-native - react-native-push-notification 无法在 android 中构建