C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で配列の全要素を等しくするための最小移動回数を求める方法

サイズ n の配列が与えられたとします。すべての配列要素を同じ値にするために必要な最小の移動回数を求めるのがこの問題の目的です。ここで「1回の移動」とは、n - 1 個の要素をそれぞれ 1 だけ増加させることを意味します。

例えば、入力が [3,2,3,4] の場合、出力は 4 になります。

解法のアプローチ

この問題を解く鍵となるのは、発想の転換です。「n - 1 個の要素を 1 増やす」という操作は、要素間の相対的な差に着目すると「1 個の要素を 1 減らす」操作と数学的に等価です。したがって、各要素を最小値まで減らすのに必要な操作回数、つまり「各要素と最小値の差の総和」が答えになります。

具体的には、以下の手順に従います。

  • n を配列 nums のサイズとします。
  • n が 0 の場合は、0 を返します。
  • 配列 nums をソートします。
  • ans を 0 で初期化します。
  • i を 0 から n - 1 まで繰り返し、ans に nums[i] - nums[0] を加算します。
  • ans を返します。

ソート後は最小値が nums[0] に位置するため、各要素と最小値の差を合計するだけで答えが求まります。計算量はソート部分が O(n log n)、合計の計算が O(n) となり、非常に効率的です。

実装例

理解を深めるために、以下の C++ 実装を見てみましょう。

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
    int minMoves(vector<int>& nums) {
        int n = nums.size();
        if (n == 0)
            return 0;
        sort(nums.begin(), nums.end());
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans += nums[i] - nums[0];
        }
        return ans;
    }
};
main(){
    Solution ob;
    vector<int> v = {3,2,3,4};
    cout << (ob.minMoves(v));
}

入力

{3,2,3,4}

出力

4

この実装では、配列 [3,2,3,4] をソートすると [2,3,3,4] となり、最小値 2 との差はそれぞれ 1、0、1、2 となります。その合計は 4 であり、期待される出力と一致します。

  1. C++で解くナイトの最短移動回数問題:メモ化再帰による効率的な解法

    問題概要無限に広がるチェス盤を考えます。座標は -∞ ~ +∞ の範囲に及び、ナイトは初期状態でマス [0, 0] に配置されています。ナイトの移動は下図のように8通りあり、それぞれ「縦または横の方向に2マス、その後それと直交する方向に1マス」という動きになります。この問題では、ナイトを目標のマス [x, y] まで移動させるのに必要な最小手数を求めます。なお、必ず目的地に到達できる(解が存在する)ことが保証されています。具体例たとえば入力が x = 5、y = 5 の場合、出力は 4 になります。これは次のような経路で到達できるためです。[0,0] → [2,1] → [4,2] → [3,

  2. 【Python】配列の全要素を等しくするための最小移動回数を求めるアルゴリズム

    問題の概要 空でない整数型の配列が与えられたとき、すべての要素を等しい値に揃えるために必要な「最小の移動回数」を求める問題を考えてみましょう。ここでいう1回の移動とは、選択した要素を +1(増加) または -1(減少) させる操作のことです。 たとえば、配列が [1, 2, 3] の場合を考えます。このとき出力は 2 になります。理由は以下の通りです。 1 を 1 回増加させて 2 にする 3 を 1 回減少させて 2 にする 2 はそのまま 合計 2 回の移動ですべての要素を 2 に揃えられるため、答えは 2 となります。 解決のためのアプローチ この問題を効率的に解く鍵となるのが中央