算法杂记 2023/02/15

算法杂记 2023/02/15

今天分享的是两个力扣上的题,都是关于如何最后使数组中所有的元素相等

453. Minimum Moves to Equal Array Elements

Given an integer array nums of size n, return the minimum number of moves required to make all array elements equal.

In one move, you can increment n - 1 elements of the array by 1.

Example 1:

Input: nums = [1,2,3]
Output: 3
Explanation: Only three moves are needed (remember each move increments two elements):
[1,2,3]  =>  [2,3,3]  =>  [3,4,3]  =>  [4,4,4]

Example 2:

Input: nums = [1,1,1]
Output: 0

Constraints:

  • n == nums.length
  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • The answer is guaranteed to fit in a 32-bit integer.

题目大意是每次操作可以使数组中 \(n-1\) 个元素 +1

假设我们需要 \(m\) 次操作,最后得到使所有的元素都等于 \(tar\)。如果我们每次操作是让所有元素\(+1\),那么所有元素初始值都应该为 \(tar - m\)。但是我们每次可以让一个元素不加一,反过来想,意思是每次操作让一个元素减\(1\),(因为最后只是要求相等,数值是没有意义的),最后使得所有元素相等。

那么就很好考虑了,我们只需要知道最小的元素是什么,并且统计答案即可,\(O(n)\)

class Solution {
public:
    int minMoves(vector<int>& nums) {
        int n = nums.size();
        int mn = 0x3f3f3f3f;
        for (int i = 0; i < n; ++ i)
            mn = min(mn, nums[i]);
        int ans = 0;
        for (int i = 0; i < n; ++ i)
            ans += nums[i] - mn;
        return ans;
    }
};

462. Minimum Moves to Equal Array Elements II

Given an integer array nums of size n, return the minimum number of moves required to make all array elements equal.

In one move, you can increment or decrement an element of the array by 1.

Test cases are designed so that the answer will fit in a 32-bit integer.

Example 1:

Input: nums = [1,2,3]
Output: 2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

Example 2:

Input: nums = [1,10,2,9]
Output: 16

Constraints:

  • n == nums.length
  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

本题是每个元素可以加一或者减一,最后使得所有元素相等,求问最小操作数。

直觉来说,肯定是一个介于中间的值,这样最大值,最小值都往这个中间值逼近肯定是最好的。

这题可以直接转化为最小曼哈顿距离,结论就是直接求中位数就好了。

这里,可以用 sort 求,当然也不能忘了快速选择算法。

这样就可以在 \(O(n)\) 的时间内解决。

这里的快速选择写的非常简洁,但实际上里面的原理分析大有道理,这里留下一个关于该写法的分析

class Solution {
public:

    int qsort(vector<int>& nums, int l, int r, int k){
        if (l == r) return nums[l];
        int i = l - 1, j = r + 1;
        int x = nums[(i + j) / 2]; // 中位数
        
        while (i < j){
            do ++i; while (nums[i] < x);
            do --j; while (x < nums[j]);
            if (i < j) swap(nums[i], nums[j]);
        }
        // 最后得到 [l, j] 是 <= x 的
        int Len = j - l + 1;
        if (Len >= k)
            return qsort(nums, l, j, k);
        return qsort(nums, j+1, r, k - Len);
    }

    int minMoves2(vector<int>& nums) {
        int n = nums.size(), ans = 0;
        int mid = qsort(nums, 0, n - 1, n / 2 + 1);
        for (int i = 0; i < n; ++ i)
            ans += abs(nums[i] - mid);
        return ans;
    }
};
posted @ 2023-02-15 18:09  Last_Whisper  阅读(14)  评论(0编辑  收藏  举报