0と1のみで構成されたソート済み配列の遷移点をC++で効率的に求める方法
0と1のみで構成されたソート済みの数値配列が与えられたとき、遷移点(トランジションポイント)を見つける問題を考えます。遷移点とは、配列内で最初に「1」が出現するインデックスのことです。
入力例1
N = 6
arr[ ] = {0,0,0,0,1,1}出力:
4
説明: 0と1で構成されたこの配列では、インデックス「4」の要素が最初の「1」になっているため、答えは4となります。
入力例2
N = 5
arr[ ] = {0,0,1,1,1}出力:
2
説明: この配列では、インデックス「2」の要素が最初の「1」であるため、2を返します。
この問題の解き方
与えられた整数配列の中から、最初に「1」が出現するインデックスを見つける必要があります。配列はすでにソートされているため、二分探索法(バイナリサーチ)を使えば、線形探索よりも高速にO(log N)の計算量で解くことができます。
- N個の2進数(0と1)からなる配列を入力として受け取ります。
- 関数 transitionPoint(int *arr, int n) は、配列とそのサイズを引数に取り、最初の「1」が出現するインデックスを返します。
- 2つのポインタ low と high を用意し、それぞれ「0」と「n-1」で初期化します。
- 配列の中央(mid)の要素を調べ、「1」であるかどうかを確認します。
- 中央の要素が「1」の場合、それが最初の「1」かどうか(直前の要素が「0」または先頭であるか)を確認し、条件を満たせばそのインデックスを返します。そうでなければ、探索範囲を左半分に狭めて続行します。
- 中央の要素が「0」の場合は、探索範囲を右半分に移動させます。
- low が high を超えるまでこの手順を繰り返します。「1」が見つからない場合は -1 を返します。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
int transitionPoint(int *arr, int n){
int low=0;
int high= n-1;
while(low<=high){
int mid = (low+high)/2;
if(arr[mid]==0)
low= mid+1;
else if(arr[mid]==1){
if(mid==0 || (mid>0 && arr[mid-1]==0))
return mid;
high= mid-1;
}
}
return -1;
}
int main(){
int n= 6;
int arr[n]= {0,0,0,1,1,1};
int ans= transitionPoint(arr,n);
if(ans>=0){
cout<<"Transition Point is:"<<ans<<endl;
}
else{
cout<<"Not Found"<<endl;
}
return 0;
}出力結果
上記のコードを実行すると、次の出力が得られます。
Transition Point is: 3
配列 {0,0,0,1,1,1} の場合、「1」はインデックス「3」に初めて出現するため、出力は「3」となります。なお、配列に「1」が一切含まれていない場合は、関数が -1 を返し、「Not Found」と表示されます。
-
C++でLCMとHCFが与えられたときにもう一方の数を求める方法
ある数Aと、その最小公倍数(LCM)および最大公約数(HCF/GCD)の値が与えられているとき、もう一方の数Bを求める問題を考えます。例えば、A = 5、LCM = 25、HCF = 4が与えられた場合、もう一方の数は20になります。この問題を解く鍵となるのは、任意の2つの数AとBの間に常に成り立つ次の重要な数学的性質です。$$𝐴∗𝐵=𝐿𝐶𝑀∗𝐻𝐶𝐹$$つまり、「2つの数の積」は「最小公倍数と最大公約数の積」と等しくなります。この式をBについて変形すると、次のようになります。$$𝐵= \frac{LCM*HCF}{A}$$アルゴリズム数A、LCM、
-
C++で配列要素の階乗の最大公約数(GCD)を求める方法
N個の要素を持つ配列Aが与えられたとき、配列内のすべての要素の階乗の最大公約数(GCD)を求めることを考えます。例えば、配列の要素が {3, 4, 8, 6} の場合、各要素の階乗は 3! = 6、4! = 24、8! = 40320、6! = 720 となり、これらのGCDは 6 になります。解法のポイントここで重要な数学的な性質があります。2つの数のGCDとは、両方の数を割り切る最大の数のことです。階乗の場合、小さい数の階乗は必ず大きい数の階乗を割り切ることができます。つまり、2つの階乗のGCDは、小さい方の数の階乗そのものになります。例えば、3! と 5! のGCDを考えると、3! =