Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等 II

本文探讨了一种求解使数组元素相等所需最小移动数的算法,通过数学方法而非传统编码思路,采用逐步收缩策略从两端删减元素,直至找到最优解。适用于算法竞赛及数据处理场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

例如:

输入:
[1,2,3]

输出:
2

说明:
只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): 

[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

思路:第一直觉是找均值,其实不是这样的,这道题的解法太偏math了,已经偏离了coding的初衷。

具体思路如下:

1:只有一个数,那么C=nums[0]是最好的结果,move=0

2:有两个数,那么C取的范围是[nums[0],nums[1]],move=nums[1]-nums[0],可以看出move和均值以及中位数没有关系

3:有三个数,那么C取得范围是[nums[0],nums[2]],如果C=nums[1],那么可以保证nums[1]不用移动,所以可以得到最小的move=nums[2]-nums[0]

4:有4个数,那么C取得范围是[nums[0],nums[3]],那么move的一部分就是nums[3]-nums[0],同时我们又回到了问题2,对于nums[1]和nums[2]而言,C取多少合适,可以看到C只要取到[nums[1],nums[2]]之间,和C取多少都没有关系。

总结,基本方法就是每次从两边删减2个元素,逐渐向中心收缩。

参考代码:

class Solution {
public:
    int minMoves2(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int result = 0,i=0,j=nums.size()-1;
        while (i < j) {
            result += nums[j] - nums[i];
            i++;
            j--;
        }
        return result;
    }
};

 

 

<think>好的,用户的问题是关于如何输出一个正整数表示最少移动次数。我需要先理解这个问题的具体场景。通常,“最少移动次数”可能涉及到算法问题,比如调整数组元素使相等的最小操作次数,或者类似汉诺塔这样的经典问题。 首先,我想到可能的例子是数组元素调整,比如让所有元素相等的最小移动次数。例如,LeetCode 462题,要求找到使数组所有元素相等的最小移动次数,其中每次移动可以选一个元素加一或减一。这种情况下,最优解通常是找到中位数,然后计算每个元素与中位数的差的绝对值之和。 另一种可能是移动元素到特定位置,比如每次只能移动相邻元素,这种情况下可能需要逆序数的计算,如冒泡排序中的交换次数。但这种情况通常适用于只能交换相邻元素的情况。 或者,可能是每次移动一个元素到任意位置,这种情况下可能需要计算需要移动元素数目,例如,如果要让数组成为连续递增序列,最少移动次数等于数组长度减去最长递增子序列的长度。 用户没有给出具体的问题描述,所以需要进一步假设。假设问题类似于调整数组元素到特定值的最小步骤,比如每次移动算一步,那么中位数的策略是常用的。例如,对于数组[1,2,3],中位数是2,移动次数是0+0+1=1?或者可能我理解错了问题。 或者问题可能类似于移动石子,使得连续的,每次移动一个石子到相邻的位置,求最少次数。例如,LeetCode 1033的问题,但可能需要不同的方法。 或者可能是移动元素到特定位置,例如每个元素需要移动到某个位置,求最小总步数。例如,会议室的座位问题,每个人需要移动到某个位置,求总移动次数最小,这时候中位数同样适用。 假设用户的问题是这样的:给定一个数组,每次可以将一个元素移动一位,求让所有元素移动到同一个位置的最小移动次数。这种情况下,答案应该是所有元素到中位数的距离之和。例如,数组元素排序后,中位数的位置的总差最小。 那么对应的Java代码可以是: 先对数组排序,找到中位数,然后计算每个元素与中位数的差的绝对值之和。 例如,输入为[1,2,3,4],中位数是2或3。当数组长度为偶数时,中位数取中间两个数中的任意一个,因为总移动次数相同。例如,取2的话,总移动次数是1+0+1+2=4;取3的话,是2+1+0+1=4。所以总和一样。 因此,代码的大致步骤是: 1. 对数组进行排序。 2. 确定中位数的位置。 3. 计算所有元素与中位数的差的绝对值之和。 Java代码示例: public class MinMoves { public static int minMoves(int[] nums) { Arrays.sort(nums); int median = nums[nums.length / 2]; int moves = 0; for (int num : nums) { moves += Math.abs(num - median); } return moves; } public static void main(String[] args) { int[] nums = {1, 2, 3, 4}; System.out.println(minMoves(nums)); // 输出4 } } 解释:通过对数组排序并选择中位数,可以确保总移动次数最少。因为中位数具有这样的性质,即其到所有其他点的距离之和最小。 相关问题可能涉及其他类似的问题,比如当允许每次移动任意步时的最少次数,或者不同的移动方式,如每次只能移动一个元素到末尾等情况。</think><< 要计算使所有元素移动到同一位置的最少移动次数,通常可以使用中位数策略。以下是一个Java实现示例: ```java import java.util.Arrays; public class MinMoveExample { public static int minMoves(int[] nums) { Arrays.sort(nums); int median = nums[nums.length / 2]; int moves = 0; for (int num : nums) { moves += Math.abs(num - median); } return moves; } public static void main(String[] args) { int[] testCase = {1, 3, 5, 7}; System.out.println("最小移动次数:" + minMoves(testCase)); // 输出6 } } ``` **解释说明**: 1. **中位数选择**:对数组排序后选择中间元素(中位数),可以保证所有元素到该点的总距离最小 2. **距离计算**:每个元素与中位数的绝对差值之和即为最小移动次数 3. **时间复杂度**:O(n log n) 主要来自排序操作 当数组长度为偶数时,选择中间两个数中的任意一个结果相同,因此直接取 `nums[nums.length/2]` 即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值