C++で配列の全要素を等しくするための最小操作回数を求める方法
問題文
N個の要素からなる配列と整数Kが与えられます。この配列に対して、以下の操作を何度でも繰り返し実行できます。
- 配列のK番目の要素を配列の末尾に挿入し、同時に配列の先頭の要素を削除する
この操作を用いて、配列のすべての要素を等しくするために必要な最小の操作回数を求めるのが課題です。もしすべての要素を等しくすることが不可能な場合は、-1を出力してください。
具体例
配列 arr[] = {1, 2, 3, 4, 5, 6}、k = 6 の場合、最小5回の操作で全要素を等しくできます。
操作1: {2, 3, 4, 5, 6, 6}
操作2: {3, 4, 5, 6, 6, 6}
操作3: {4, 5, 6, 6, 6, 6}
操作4: {5, 6, 6, 6, 6, 6}
操作5: {6, 6, 6, 6, 6, 6}アルゴリズム
この問題は以下の手順で解くことができます。
- まず a[k] を末尾にコピーし、続いて a[k+1]、a[k+2] と順番に末尾へコピーしていきます。
- 等しい要素だけがコピーされることを保証するため、K番目からN番目までの範囲のすべての要素が等しい必要があります。また、1番目からK番目までの範囲に存在する a[k] と異なる要素は、すべて削除される必要があります。
- 1番目からK番目までの範囲で、a[k] と等しくない最も右側の要素に到達するまで操作を繰り返し適用します。
つまり、後半部分(K〜N)に異なる値が含まれている場合は答えは -1 となり、そうでなければ、前半部分(1〜K)の中で a[k] と異なる最後の要素の位置がそのまま必要な操作回数になります。
C++での実装例
#include <iostream>
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
using namespace std;
int getMinMoves(int *arr, int n, int k){
int i;
// K番目以降の要素がすべて等しいかチェック
for (i = k - 1; i < n; ++i) {
if (arr[i] != arr[k - 1]) {
return -1;
}
}
// 前半部分で a[k-1] と異なる最も右側の要素を探す
for (i = k - 1; i >= 0; --i) {
if (arr[i] != arr[k - 1]) {
return i + 1;
}
}
return 0;
}
int main(){
int arr[] = {1, 2, 3, 4, 5, 6};
int k = 6;
cout << "Minimum moves required = " << getMinMoves(arr, SIZE(arr), k) << endl;
return 0;
}出力結果
上記のプログラムをコンパイルして実行すると、以下の出力が得られます。
Minimum moves required = 5
計算量について
このアルゴリズムの時間計算量は O(N) です。配列を最大2回走査するだけで答えが求まるため、非常に効率的です。空間計算量も O(1) と、追加のメモリをほとんど必要としません。
-
C++で配列を「良い配列」にするために削除が必要な最小要素数を求めるアルゴリズム
問題の概要整数型配列「arr」が与えられたとき、この配列を「良い配列」にするために削除する必要がある要素の最小数を求めるのが課題です。ここで「良い配列」とは、数列 a1, a2, a3, ... an の各要素 a[i] に対して、i ≠ j を満たす別の要素 a[j] が必ず存在し、a[i] + a[j] の和が2の累乗(べき乗)になるような配列のことを指します。具体例arr1[] = {1, 1, 7, 1, 5}上記の配列では、要素「5」を1つ削除するだけで配列は良い配列になります。削除後は、任意のペア arr[i] + arr[j] の和が2の累乗になります。arr[0] + arr[
-
C++で配列の全要素を同じ値にするための最小削除操作数を求めるアルゴリズム
問題概要n個の要素からなる配列が与えられます。要素には重複が含まれる場合があります。この配列から任意の数の要素を削除できるとき、すべての要素を同じ値にするために必要な最小の削除数を求めるのが課題です。例として、次の配列を考えてみましょう。arr[] = {10, 8, 10, 7, 10, -1, -4, 12}この場合、最も多く出現している「10」以外の5つの要素を削除すれば、配列の全要素を10で統一できます。つまり、答えは5回の削除となります。解法の考え方この問題の鍵となるのは、「削除する量を最小化する = 残す要素の数を最大化する」という発想です。全要素を同じ値にするためには、必ずどれか