【发布时间】:2021-03-27 02:46:42
【问题描述】:
给你一个偶数长度的整数列表。考虑一个操作,您可以在 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,nums[2] + nums[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,5,4,5,9,3]的变换为例,你得带我一步一步来。
-
@GilbertLeBlanc 我在示例中添加了一些解释。如果您需要更多详细信息,请告诉我。
-
为什么是中位数?模式不是更有用吗,即最常出现的总和,这意味着大多数数字对不必调整?
-
@tobias_k 对于 nums = [10, 7, 2, 9, 4, 1, 7, 3, 10, 8],总和为 [5, 5, 16, 17, 18] 和如果选择 5,因为它出现了两次,操作数仍然是 6。如何? (10 + 8 > 5) (7 + 10 > 5) (9 + 7 > 5) 都需要 2 次操作来改变并使和等于 5,因此总共需要 6 次操作。
-
嗯,我不知道有什么证明之类的,但取中位数似乎是合理的,因为它似乎是最接近 sum 的所有其他元素的可能值。