comments | difficulty | edit_url | tags | |||
---|---|---|---|---|---|---|
true |
中等 |
|
给你一个长度为 n
的整数数组 nums
,返回使所有数组元素相等需要的最小操作数。
在一次操作中,你可以使数组中的一个元素加 1
或者减 1
。
测试用例经过设计以使答案在 32 位 整数范围内。
示例 1:
输入:nums = [1,2,3] 输出:2 解释: 只需要两次操作(每次操作指南使一个元素加 1 或减 1): [1,2,3] => [2,2,3] => [2,2,2]
示例 2:
输入:nums = [1,10,2,9] 输出:16
提示:
n == nums.length
1 <= nums.length <= 105
-109 <= nums[i] <= 109
这个问题可以抽象为,在数轴上有
中位数有这样的性质:所有数与中位数的距离之和最小。
证明:
首先,给定一个从小到大的数列
在这个问题中,我们可以先对数组进行排序,然后找到中位数,最后计算所有数与中位数的距离之和即可。
时间复杂度
相似题目:
class Solution:
def minMoves2(self, nums: List[int]) -> int:
nums.sort()
k = nums[len(nums) >> 1]
return sum(abs(v - k) for v in nums)
class Solution {
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int k = nums[nums.length >> 1];
int ans = 0;
for (int v : nums) {
ans += Math.abs(v - k);
}
return ans;
}
}
class Solution {
public:
int minMoves2(vector<int>& nums) {
sort(nums.begin(), nums.end());
int k = nums[nums.size() >> 1];
int ans = 0;
for (int& v : nums) ans += abs(v - k);
return ans;
}
};
func minMoves2(nums []int) int {
sort.Ints(nums)
k := nums[len(nums)>>1]
ans := 0
for _, v := range nums {
ans += abs(v - k)
}
return ans
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
function minMoves2(nums: number[]): number {
nums.sort((a, b) => a - b);
const mid = nums[nums.length >> 1];
return nums.reduce((r, v) => r + Math.abs(v - mid), 0);
}
impl Solution {
pub fn min_moves2(mut nums: Vec<i32>) -> i32 {
nums.sort();
let mid = nums[nums.len() / 2];
let mut res = 0;
for num in nums.iter() {
res += (num - mid).abs();
}
res
}
}
如果我们不知道中位数的性质,也可以使用前缀和的方法来求解。
时间复杂度
class Solution:
def minMoves2(self, nums: List[int]) -> int:
def move(i):
v = nums[i]
a = v * i - s[i]
b = s[-1] - s[i + 1] - v * (n - i - 1)
return a + b
nums.sort()
s = [0] + list(accumulate(nums))
n = len(nums)
return min(move(i) for i in range(n))