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

C++で配列を分割してソートする際の最大チャンク数を求める方法

問題の概要

[0, 1, ..., arr.length - 1] の順列(パーミュテーション)である配列 arr が与えられたとします。この配列をいくつかの「チャンク(区切り)」に分割し、それぞれのチャンクを個別にソートします。その後、すべてのチャンクを連結した結果が、完全にソートされた配列になるとき、作成できるチャンク数の最大値を求めるのがこの問題です。

例えば、配列が [1,0,2,3,4] の場合、出力は 4 になります。[1, 0] と [2,3,4] のように2つのパーティションに分割することもできますが、[1, 0]、[2]、[3]、[4] のように4つに分割することも可能です。これが作成可能な最大チャンク数となるため、答えは 4 になります。

それでは、作成できるチャンク数の最大値はいくつになるのでしょうか?

解法のアプローチ

この問題を解くために、以下の手順に従います。

  • ans := 0、minVal := 無限大、n := 配列のサイズ、maxVal := 負の無限大 として初期化します
  • i を 0 から n までループさせます
    • maxVal := arr[i] と maxVal のうち大きい方を代入します
    • maxVal == i であれば、ans を 1 増やします
  • 最後に ans を返します

このアルゴリズムが正しく動作する理由は、配列が [0, n-1] の順列であることにあります。インデックス i までの要素の最大値がちょうど i と一致するとき、その位置までの部分配列は「0 から i までの値をすべて含む集合」となり、そこで区切っても全体のソート結果に影響しないため、独立したチャンクとして扱えるのです。

C++による実装例

より深く理解するために、以下の実装例を見てみましょう。

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
   int maxChunksToSorted(vector<int>& arr) {
      int ans = 0;
      int minVal = INT_MAX;
      int n = arr.size();
      int maxVal = INT_MIN;
      for(int i = 0; i < n; i++){
         maxVal = max(arr[i], maxVal);
         if(maxVal == i){
            ans++;
         }
      }
      return ans;
   }
};
main(){
   Solution ob;
   vector<int> v = {1,0,2,3,4};
   cout << (ob.maxChunksToSorted(v));
}

入力

[1,0,2,3,4]

出力

4

計算量について

このアルゴリズムは配列を一度走査するだけなので、時間計算量は O(n)、追加のデータ構造を使用しないため空間計算量は O(1) となります。非常に効率的な解法と言えるでしょう。

  1. C++で同一直線上に存在する最大点数を求めるアルゴリズム

    問題概要 2次元平面上に複数の点が与えられたとき、同じ直線上に存在する点の最大数を求めるのがこの問題の目的です。 例えば、下図のような6つの点が与えられた場合、最も多くの点が乗っている直線上には4つの点が存在します。 解法のアプローチ この問題は、隣り合う2点を通る直線を基準にして、残りのすべての点がその直線上に乗っているかどうかを順番に判定していくことで解けます。 3点 (x1, y1)、(x2, y2)、(x3, y3) が同一直線上にあるかどうかは、「傾きが等しい」こと、すなわち外積(クロス積)が0になることを利用して判定できます。 (y3 − y2) × (x2 − x1) = (

  2. Pythonで配列をソート済みにできる最大チャンク数を見つけるプログラム

    問題の概要 配列 nums が与えられたとき、この配列をいくつかの区間(パーティション/チャンク)に分割し、それぞれを個別にソートします。その後、すべてを連結した結果が完全にソート済みの配列になるとします。このとき、作成できるパーティションの最大数を求めるのが本記事のテーマです。 例えば、入力が [3,2,4,5,5] の場合、出力は 4 になります。[3,2]、[4][5]、[5] のように4つのパーティションに分割でき、それぞれをソートして連結すると [2,3,4,5,5] という完全に整列した配列が得られるからです。 解法のアプローチ この問題は「貪欲法」で解くことができます。ある区間