Minimum Operations to Make All Array Elements Equal
For each query, sort once and use prefix sums plus binary search to compute the total deviation.
5 min read
prefix-sum binary-search sorting
Problem#
For each query q, return the minimum number of unit operations (each increments or decrements one element by 1) to make every element of nums equal to q. Answer each query independently.
Examples#
nums = [3,1,6,8], queries = [1,5]→[14,10]nums = [2,9,6,3], queries = [10]→[20]
Constraints#
1 <= nums.length, queries.length <= 10^5,1 <= nums[i], queries[i] <= 10^9.
Approach#
Sort nums and build a prefix sum. For query q, find the split index where elements switch from <= q to > q via upper_bound. The cost is (q * k - leftSum) + (rightSum - q * (n - k)).
Solution#
class Solution {public: vector<long long> minOperations(vector<int>& nums, vector<int>& queries) { sort(nums.begin(), nums.end()); int n = nums.size(); vector<long long> pref(n + 1, 0); for (int i = 0; i < n; ++i) pref[i + 1] = pref[i] + nums[i]; vector<long long> ans; ans.reserve(queries.size()); for (int q : queries) { int k = upper_bound(nums.begin(), nums.end(), q) - nums.begin(); long long left = (long long)q * k - pref[k]; long long right = (pref[n] - pref[k]) - (long long)q * (n - k); ans.push_back(left + right); } return ans; }};func minOperations(nums []int, queries []int) []int64 { sort.Ints(nums) n := len(nums) pref := make([]int64, n+1) for i := 0; i < n; i++ { pref[i+1] = pref[i] + int64(nums[i]) } ans := make([]int64, 0, len(queries)) for _, q := range queries { k := sort.SearchInts(nums, q+1) left := int64(q)*int64(k) - pref[k] right := (pref[n] - pref[k]) - int64(q)*int64(n-k) ans = append(ans, left+right) } return ans}import bisectfrom typing import List
class Solution: def minOperations(self, nums: List[int], queries: List[int]) -> List[int]: nums.sort() n = len(nums) pref = [0] * (n + 1) for i in range(n): pref[i + 1] = pref[i] + nums[i] ans = [] for q in queries: k = bisect.bisect_right(nums, q) left = q * k - pref[k] right = (pref[n] - pref[k]) - q * (n - k) ans.append(left + right) return ansfunction minOperations(nums, queries) { nums.sort((a, b) => a - b); const n = nums.length; const pref = new Array(n + 1).fill(0n); for (let i = 0; i < n; i++) pref[i + 1] = pref[i] + BigInt(nums[i]); const upperBound = (q) => { let lo = 0, hi = n; while (lo < hi) { const mid = (lo + hi) >> 1; if (nums[mid] <= q) lo = mid + 1; else hi = mid; } return lo; }; const ans = []; for (const q of queries) { const k = upperBound(q); const qb = BigInt(q); const left = qb * BigInt(k) - pref[k]; const right = (pref[n] - pref[k]) - qb * BigInt(n - k); ans.push(Number(left + right)); } return ans;}class Solution { public List<Long> minOperations(int[] nums, int[] queries) { Arrays.sort(nums); int n = nums.length; long[] pref = new long[n + 1]; for (int i = 0; i < n; i++) pref[i + 1] = pref[i] + nums[i]; List<Long> ans = new ArrayList<>(queries.length); for (int q : queries) { int k = upperBound(nums, q); long left = (long) q * k - pref[k]; long right = (pref[n] - pref[k]) - (long) q * (n - k); ans.add(left + right); } return ans; }
private int upperBound(int[] nums, int q) { int lo = 0, hi = nums.length; while (lo < hi) { int mid = (lo + hi) >>> 1; if (nums[mid] <= q) lo = mid + 1; else hi = mid; } return lo; }}function minOperations(nums: number[], queries: number[]): number[] { nums.sort((a, b) => a - b); const n = nums.length; const pref: bigint[] = new Array(n + 1).fill(0n); for (let i = 0; i < n; i++) pref[i + 1] = pref[i] + BigInt(nums[i]); const upperBound = (q: number): number => { let lo = 0, hi = n; while (lo < hi) { const mid = (lo + hi) >> 1; if (nums[mid] <= q) lo = mid + 1; else hi = mid; } return lo; }; const ans: number[] = []; for (const q of queries) { const k = upperBound(q); const qb = BigInt(q); const left = qb * BigInt(k) - pref[k]; const right = (pref[n] - pref[k]) - qb * BigInt(n - k); ans.push(Number(left + right)); } return ans;}Editorial#
For each split point, every element below contributes q - x and every element above contributes x - q. Prefix sums collapse those summations into O(1) per query after O(n log n) preprocessing.
Complexity#
- Time: O((n + q) log n).
- Space: O(n).
Concept revision#
Related#