赞
踩
给你一个长度为 n
的整数数组 nums
,返回使所有数组元素相等需要的最小操作数。
在一次操作中,你可以使数组中的一个元素加 1
或者减 1
。
输入:nums = [1,2,3]
输出:2
解释:
只需要两次操作(每次操作指南使一个元素加 1 或减 1):
[1,2,3] => [2,2,3] => [2,2,2]
输入:nums = [1,10,2,9]
输出:16
每次可以对一个数组元素加一或者减一,求最小的改变次数。
这是个典型的相遇问题,移动距离最小的方式是所有元素都移动到中位数。理由如下:
m
为中位数。a
和 b
是 m
两边的两个元素,且 b > a
。a
和 b
相等,它们总共移动的次数为 b - a
,这个值等于 (b - m) + (m - a)
,设数组长度为 N
,则可以找到 N/2
对 a
和 b
的组合,使它们都移动到 m
的位置。
Java
import java.util.Arrays; public class MinMoves2 { public static void main(String[] args) { // TODO Auto-generated method stub int[] nums = {1, 10, 2, 9}; System.out.println(minMoves2(nums)); } public static int minMoves2(int[] nums) { Arrays.sort(nums); int l = 0, h = nums.length - 1; int moves = 0; while(l < h) { moves += nums[h--] - nums[l++]; } return moves; } }
C++
#include <iostream> #include <vector> #include <algorithm> using namespace std; class MinMoves2 { public: int minMoves2(vector<int>& nums) { sort(nums.begin(), nums.end()); int l = 0, h = nums.size() - 1; int moves = 0; while (l < h) { moves += nums[h--] - nums[l++]; } return moves; } }; int main() { MinMoves2 m; vector<int> nums = {1,10,2,9 }; cout << m.minMoves2(nums) << endl; system("pause"); return 0; }
n
是数组 nums
的长度。排序需要
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的时间。题目来源:力扣。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。