本文涉及的基础知识点
C++二分查找
C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频
LeetCode2602. 使数组元素全部相等的最少操作次数
同时给你一个长度为 m 的整数数组 queries 。第 i 个查询中,你需要将 nums 中所有元素变成 queries[i] 。你可以执行以下操作 任意 次:
将数组里一个元素 增大 或者 减小 1 。
请你返回一个长度为 m 的数组 answer ,其中 answer[i]是将 nums 中所有元素变成 queries[i] 的 最少 操作次数。
注意,每次查询后,数组变回最开始的值。
示例 1:
输入:nums = [3,1,6,8], queries = [1,5]
输出:[14,10]
解释:第一个查询,我们可以执行以下操作:
- 将 nums[0] 减小 2 次,nums = [1,1,6,8] 。
- 将 nums[2] 减小 5 次,nums = [1,1,1,8] 。
- 将 nums[3] 减小 7 次,nums = [1,1,1,1] 。
第一个查询的总操作次数为 2 + 5 + 7 = 14 。
第二个查询,我们可以执行以下操作: - 将 nums[0] 增大 2 次,nums = [5,1,6,8] 。
- 将 nums[1] 增大 4 次,nums = [5,5,6,8] 。
- 将 nums[2] 减小 1 次,nums = [5,5,5,8] 。
- 将 nums[3] 减小 3 次,nums = [5,5,5,5] 。
第二个查询的总操作次数为 2 + 4 + 1 + 3 = 10 。
示例 2:
输入:nums = [2,9,6,3], queries = [10]
输出:[20]
解释:我们可以将数组中所有元素都增大到 10 ,总操作次数为 8 + 1 + 4 + 7 = 20 。
提示:
n == nums.length
m == queries.length
1 <= n, m <= 105
1 <= nums[i], queries[i] <= 109
C++二分查找
n = nums.size()
对num按升序排序,令nums[0…j-1]都小于que[i], nums[j…]都大于等于que[i]。
则结果是:que[i] × \times ×j - nums[0…j-1]之和 + nums[j…]之和- que[i] × \times ×(n-j)
求子数组之和用前缀和。
代码
核心代码
class Solution {
public:
vector<long long> minOperations(vector<int>& nums, vector<int>& queries) {
sort(nums.begin(), nums.end());
vector<long long> preSum(1);
for (const auto& n : nums) {
preSum.emplace_back(n + preSum.back());
}
vector<long long> ret;
for (const long long que : queries) {
int j = lower_bound(nums.begin(), nums.end(), que) - nums.begin();
const long long cur =que * j - preSum[j] + (preSum.back() - preSum[j]) - que * (nums.size() - j);
ret.emplace_back(cur);
}
return ret;
}
};
单元测试
vector<int> nums, queries;
TEST_METHOD(TestMethod11)
{
nums = { 3, 1, 6, 8 }, queries = { 1, 5 };
auto res = Solution().minOperations(nums, queries);
AssertEx({ 14,10 }, res);
}
TEST_METHOD(TestMethod12)
{
nums = { 2,9,6,3 }, queries = {10 };
auto res = Solution().minOperations(nums, queries);
AssertEx({ 20 }, res);
}