C++で等比数列の欠けている数を見つける方法
等比数列の各項が順番に格納された配列があるとします。しかし、そのうちの1つの要素が欠けてしまっています。ここでの課題は、この欠けている要素を見つけることです。
例えば、arr = [1, 3, 27, 81] という配列が与えられた場合、本来は 9 が入るべき位置が空いているため、出力は 9 となります。
二分探索によるアプローチ
この問題は二分探索(バイナリサーチ)を使うことで効率的に解くことができます。基本的な考え方は以下の通りです。
- まず配列の中央要素(mid)に着目し、中央要素とその隣の要素との比が、数列の公比と一致しているかどうかを確認します。
- もし比が一致しなければ、欠けている要素は mid と mid + 1 のインデックスの間に存在することになります。
- 中央要素が等比数列の n/2 番目の位置として正しければ、欠けている要素は右半分にあります。そうでなければ左半分にあります。
この処理を再帰的に繰り返すことで、時間計算量 O(log n) で欠けている要素を特定できます。
サンプルコード
#include <iostream>
#include <cmath>
using namespace std;
class Progression {
public:
int missingUtil(int arr[], int left, int right, int ratio) {
if (right <= left)
return INT_MAX;
int mid = left + (right - left) / 2;
if (arr[mid + 1] - arr[mid] != ratio)
return (arr[mid] * ratio);
if (mid > 0 && arr[mid] / arr[mid - 1] != ratio)
return (arr[mid - 1] * ratio);
if (arr[mid] == arr[0] * pow(ratio, mid))
return missingUtil(arr, mid + 1, right, ratio);
return missingUtil(arr, left, mid - 1, ratio);
}
int missingElement(int arr[], int n) {
int ratio = pow(arr[n-1]/arr[0], 1.0/n);
return missingUtil(arr, 0, n - 1, ratio);
}
};
int main() {
Progression pg;
int arr[] = {1, 3, 27, 81};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "The missing element is: " << pg.missingElement(arr, n);
}
実行結果
The missing element is: 9
コードの解説
missingElement 関数では、最初の要素と最後の要素から公比を計算しています。pow(arr[n-1]/arr[0], 1.0/n) により、全体の比の n 乗根を求めることで公比を導き出します。
missingUtil 関数は再帰的に二分探索を行う本体です。中央要素と隣接要素の関係、および中央要素が理論値(arr[0] * pow(ratio, mid))と一致するかどうかを判定し、探索範囲を半分ずつ絞り込んでいく仕組みです。
-
C++で数を割り切る桁の個数を求める方法
問題の概要ある整数が与えられたとき、その数を割り切る桁(各桁の数字)の個数を数える問題です。例として、数が 1012 の場合を考えてみましょう。この場合、答えは 3 となります。1、1、2 の3つの桁がそれぞれ 1012 を割り切れるためです。解法のアプローチこの問題を解くには、剰余演算(% 演算子)を使って数の各桁を1つずつ取り出し、元の数がその桁の値で割り切れるかどうかを判定します。割り切れる場合はカウンターを1つ増やします。なお、桁が 0 の場合は 0 で割ることができないため、その桁はスキップ(無視)します。アルゴリズムの流れ元の数のコピーを作成し、0 になるまでループを繰り返します。
-
C++で配列内の数値の頻度(出現回数)を求める方法
配列に n 個の異なる要素が格納されているとします。この配列の中から、特定の要素が何回出現するか(頻度)を調べたい場合があります。例えば、配列 A = [5, 12, 26, 5, 3, 4, 15, 5, 8, 4] の中で「5」の頻度を調べると、答えは 3 になります。アルゴリズムの考え方この問題は、次の手順で解くことができます。1. 配列を左端から順に走査します。2. 現在の要素が調べたい数値と一致したら、カウンターを1つ増やします。3. 一致しない場合は、そのまま次の要素へ進みます。4. 配列の最後まで走査したら、カウンターの値が頻度となります。このアルゴリズムの計算量は O(n) で