C++で配列を条件を満たす2つの部分配列に分割する方法
問題の概要
配列 A が与えられたとき、それを left と right という 2 つの部分配列に分割することを考えます。分割は以下の条件を満たす必要があります。
- left 部分配列のすべての要素は、right 部分配列のすべての要素以下である
- left と right はどちらも空であってはならない
- left のサイズは可能な限り小さくする
このような分割を行った後の left の長さを求めます。なお、条件を満たす分割が存在することは保証されています。
例えば、入力が [5,0,3,8,6] の場合、出力は 3 になります。このとき left は [5,0,3]、right は [8,6] となるためです。
アルゴリズムの考え方
この問題は、接頭辞最大値(prefix max)と接尾辞最小値(suffix min)を組み合わせることで、効率的に解くことができます。手順は以下の通りです。
- n := A のサイズとし、サイズ n の配列 maxx を作成する
- minVal := A の最後の要素とする
- maxx[0] := A[0] とする
- i が 1 から n-1 までの範囲で、maxx[i] := max(A[i], maxx[i-1]) と更新する(maxx[i] は A[0..i] の最大値を表す)
- ans := A のサイズ - 1 で初期化する
- i を n-1 から 1 まで逆順に処理する
- minVal := min(minVal, A[i]) と更新する(minVal は A[i..n-1] の最小値を表す)
- minVal >= maxx[i-1] が成り立つ場合、ans := i とする
- ans を返す
実装例
以下に C++ による実装を示します。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int partitionDisjoint(vector <int>& A) {
int n = A.size();
vector <int> maxx(n);
int minVal = A[n - 1];
maxx[0] = A[0];
for(int i = 1; i < n; i++){
maxx[i] = max(A[i], maxx[i - 1]);
}
int ans = A.size() - 1;
for(int i = n - 1; i >= 1; i--){
minVal = min(minVal, A[i]);
if(minVal >= maxx[i - 1]){
ans = i;
}
}
return ans;
}
};
main(){
vector<int> v1 = {5,0,3,8,6};
Solution ob;
cout << (ob.partitionDisjoint(v1));
}
入力
[5,0,3,8,6]
出力
3
計算量
このアルゴリズムの時間計算量は O(n)、空間計算量も O(n) です。配列を前方向と後ろ方向にそれぞれ 1 回ずつ走査するだけで済むため、大規模な入力に対しても効率的に動作します。
-
【C++入門】配列を関数に渡す3つの方法をわかりやすく解説
C++では、配列全体をそのまま関数の引数として渡すことはできません。しかし、インデックスを付けずに配列名を指定することで、配列へのポインタを渡すことができます。これは「配列名は先頭要素へのポインタに読み替えられる(配列の減衰)」というC++の仕組みによるものです。1次元配列を関数の引数として渡したい場合は、以下の3つのいずれかの方法で関数の仮引数を宣言します。どの方法でも、コンパイラに対して「整数型のポインタを受け取る」という情報が伝わるため、動作結果はすべて同じになります。配列を関数に渡す3つの宣言方法1. ポインタとして仮引数を宣言するvoid myFunction(int *param)
-
Pythonで配列を互いに素な左右の部分配列に分割する方法を解説
問題の概要 配列 nums が与えられたとき、これを「left」と「right」という2つの部分配列に分割します。この分割は、以下の条件を満たす必要があります。 left 内のすべての要素が、right 内のどの要素以下であること left と right がどちらも空でないこと left のサイズが可能な限り小さいこと そして、このような分割を行った後の left の長さを求めます。 具体例 たとえば、入力が nums = [5,0,3,8,6] の場合、出力は 3 になります。これは、left 配列が [5,0,3]、right 部分配列が [8,6] に分割されるためです。 解法のア