-
C++で配列の全要素を同じ値にするための最小削除操作数を求めるアルゴリズム
問題概要n個の要素からなる配列が与えられます。要素には重複が含まれる場合があります。この配列から任意の数の要素を削除できるとき、すべての要素を同じ値にするために必要な最小の削除数を求めるのが課題です。例として、次の配列を考えてみましょう。arr[] = {10, 8, 10, 7, 10, -1, -4, 12}この場合、最も多く出現している「10」以外の5つの要素を削除すれば、配列の全要素を10で統一できます。つまり、答えは5回の削除となります。解法の考え方この問題の鍵となるのは、「削除する量を最小化する = 残す要素の数を最大化する」という発想です。全要素を同じ値にするためには、必ずどれか
-
C++で最大ヒープから最小値の要素を見つける方法
問題の概要最大ヒープ(max heap)の中から、最も小さい値を持つ要素を探す方法を解説します。以下のような最大ヒープを例に考えてみましょう。最大ヒープでは、親ノードの値は必ずその子ノードの値以上になります。この性質により、最小値は必ず葉ノード(leaf node)のいずれかに存在すると結論できます。ヒープが n 個のノードを含む場合、葉ノードの数は ceil(n/2) 個になります。また、最大ヒープは完全二分木であるため、配列として表現することができます。このとき、最初の葉ノードは floor(n/2) のインデックス以降に配置されます。上記の例では、最初の葉ノードはインデックス 5 に存在
-
【C++】2つのバイナリ配列のXORを別の配列と等しくするための最小フリップ回数
問題文 0と1のみから構成される、長さnの3つの配列が与えられます。求めたいのは、1つ目と2つ目の配列のビットをできるだけ少ない回数反転(フリップ)させて、「1つ目の配列のi番目の要素」と「2つ目の配列のi番目の要素」のXORが、「3つ目の配列のi番目の要素」と一致するようにするための最小反転回数です。 ただし、配列1については最大p個、配列2については最大q個までしかビットを反転できません。また、配列の要素を並べ替えることは許されていません。 ここでは、p = 2、q = 5 の場合を例に考えてみましょう。 arr1[] = {1, 0, 1, 1, 0, 1, 0} arr2[] = {
-
C++でk個のセットビットを持つ数を最大化するために必要な最小フリップ回数
問題文2つの整数 n と k が与えられます。n のビットを反転(フリップ)して、結果の数がちょうど k 個のセットビット(値が1のビット)を持ち、かつ取り得る最大の数になるようにするために必要な、最小のフリップ回数を求めてください。なお、入力は「k が n のビット数より小さい」という条件を満たす必要があります。例n = 9、k = 2 とします。9 の2進表現は 1001 であり、4ビットで構成されています。4桁の2進数の中でセットビットが2個となる最大の数は 1100、すなわち10進数の 12 です。1001 を 1100 に変換するには、2ビットを反転する必要があります。アルゴリズム1
-
C++で2つの行列が同一かどうかを判定するプログラム
ここでは、行数 r・列数 c を持つ2つの行列 M1[r][c] と M2[r][c] が与えられたときに、その2つの行列が同一であるかどうかを判定します。同一であれば「Matrices are identical(行列は同一)」と出力し、同一でなければ「Matrices are not identical(行列は同一ではない)」と出力します。 同一の行列とは? 2つの行列 M1 と M2 が「同一」であるとみなされるのは、以下の条件を満たす場合です。 両方の行列の行数と列数が一致していること。 すべての要素で M1[i][j] == M2[i][j] が成り立つこと。 例えば、次の3×
-
C++で速度をkm/hからm/sへ、またはその逆へ変換するプログラム
日常的なプログラミングでは、速度の単位を変換する場面がよくあります。本記事では、C++を使って速度をkm/h(キロメートル毎時)からm/s(メートル毎秒)へ、またはその逆へ変換するプログラムをわかりやすく解説します。 変換公式 km/hとm/sの間の変換には、以下の公式を使用します。 1 km/h = 5/18 m/s = 0.277778 m/s 1 m/s = 18/5 km/h = 3.6 km/h この公式は、1 km = 1000 m、1時間 = 3600秒という関係から導かれたものです(1000 ÷ 3600 = 5/18)。 入出力例 入力: km = 60.00 m
-
16進数を2進数に変換するC++プログラムの実装方法
16進数と2進数の基本 コンピュータの世界では、16進数は基数16で表現される記法です。扱う数字は0〜15ですが、10以上の値はアルファベットで表され、10はA、11はB、12はC、13はD、14はE、15はFに対応します。一方、2進数は「0」と「1」の2種類の数字のみを使用する基数2の記法です。 16進数を2進数へ変換するときは、各桁(1文字)をそれぞれ4ビットの2進数に置き換え、それらを左から順に連結します。こうすることで、元の16進数に対応する完全な2進数が得られます。 変換例 たとえば、入力「123B」を2進数に変換する場合は以下のようになります。 入力 : 123B 1
-
C++でNが五角数(ペンタゴナル数)かどうかを判定するプログラム
五角数とはある整数 N が与えられたとき、それが五角数(ペンタゴナル数)であるかどうかを判定するのが本記事の目的です。五角数とは、点を並べることで正五角形の形を描くことができる数のことです。これらの数は、五角形を構成する頂点や点として表現できます。五角数の例としては、次のような数列が挙げられます。1, 5, 12, 22, 35, 51, 70, 92 …五角数を判定する公式ある数が五角数かどうかは、以下の公式を利用して確認できます。p(n) = (3 × n² − n) / 2ここで、n は五角形を構成する点の個数を表します。この式から得られる値が順に 1, 5, 12, 22, 35… と
-
N回折りたたんだ後の正方形の面積を求めるC++プログラム
正方形の一辺の長さと折りたたむ回数が与えられたとき、n回折りたたんだ後の正方形の面積を求めるのがこの記事のテーマです。 正方形とは、長方形と同じく2次元の図形で、4つの辺がすべて等しく、すべての内角が90度であるという特徴を持ちます。 正方形を折りたたむ際は、以下の手順に従います。 1回目:正方形の左上から右下に向かって折り、三角形を作ります。 2回目:上から下へ折りたたみます。 3回目:再び左から右へ折りたたみます。 4回目以降も、同じ手順を繰り返します。 入出力例 入力:side = 23, fold = 4 出力:n回折りたたんだ後の正方形の面積:6.53086 解き方のアプローチ
-
C++で正方形の面積を求めるプログラムの書き方
本記事では、正方形の一辺が与えられたときに、その一辺をもとに正方形の面積を計算して出力するC++プログラムを紹介します。 正方形とは 正方形とは、4つの辺と4つの角(すべて90度)を持つ2次元の平面図形であり、すべての辺の長さが等しいという特徴があります。言い換えれば、正方形とは「すべての辺の長さが等しい長方形」の一種であるとも言えます。 正方形のイメージは以下の通りです。 正方形の面積 = 一辺 × 一辺 入力例と出力例 入力:6 出力:36 一辺が6なので、出力は 6×6=36 となります。 入力:12 出力:144 アルゴリズム 処理の流れは以下のようになります。 関数 int m
-
C++でセットビット数に基づいて配列をソートする方法
今回は、配列を「セットビット」の数に基づいてソートするという興味深い問題を取り上げます。セットビットとは、数値を2進数で表したときに「1」となっているビットのことです。セットビット数が多い要素ほど、少ない要素よりも前に配置されるように並べ替えます。例として、12・15・7 という3つの数値を考えてみましょう。それぞれの2進数表現とセットビット数は次のとおりです。1100 (12) → セットビット数 21111 (15) → セットビット数 40111 (7) → セットビット数 3これをセットビット数の降順でソートすると、結果は以下のようになります。1111, 0111, 1100 (つま
-
C++で別の配列の順序に従って配列を並べ替える方法
問題の概要 この記事では、少し変わったソートの問題を取り上げます。2つの配列 A1 と A2 が与えられたとき、A1 を「A2 で定義された相対的な順序」に従って並べ替えます。A2 に存在しない要素は、並べ替えられた要素の後ろに続けて配置します。 たとえば、次のような配列を考えてみましょう。 A1 = {2, 1, 2, 1, 7, 5, 9, 3, 8, 6, 8} A2 = {2, 1, 8, 3} ソート後、A1 は次のようになります。 A1 = {2, 2, 1, 1, 8, 8, 3, 5, 6, 7, 9} A2 に含まれる要素(2, 1, 8, 3)は A2 の出現順に並び、そ
-
C++で文字列の長さに基づいて文字列の配列をソートする方法
この記事では、文字列のリストをその長さに基づいてソートする方法について解説します。文字数が少ない文字列ほど先頭に配置され、それより長い文字列が後ろに並びます。例として、次のような文字列の配列があるとします。 str_list = {Hello, ABC, Programming, Length, Population} これをソートすると、以下のようになります。 str_list = {ABC, Hello, Length, Population, Programming} ここでは、独自の比較ロジックを作成してソートを行います。この比較関数は、C++ STL の std::sort 関数に
-
C++で桁の合計に基づいて数値をソートする方法
この記事では、各数値の「桁の合計(各桁の数字を足した値)」に基づいて数値を並べ替える方法を解説します。桁の合計が小さい数値ほど先頭に配置され、合計が大きい数値ほど後ろに配置されます。ソートの例例として、次のようなデータを考えてみましょう。data = {14, 129, 501, 23, 0, 145}このデータを桁の合計順にソートすると、以下のようになります。0 → 桁の合計は 014 → 桁の合計は 1 + 4 = 523 → 桁の合計は 2 + 3 = 5501 → 桁の合計は 5 + 0 + 1 = 6145 → 桁の合計は 1 + 4 + 5 = 10129 → 桁の合計は 1 +
-
C++でテトラナッチ数列を生成する方法
この記事では、C++を使ってテトラナッチ(Tetranacci)数を生成する方法を解説します。テトラナッチ数はフィボナッチ数によく似た数列ですが、フィボナッチ数が直前の2つの項の和で次の項を求めるのに対し、テトラナッチ数では直前の4つの項をすべて足し合わせて新しい項を生成する点が特徴です。n番目の項 T(n) を求める漸化式は以下の通りです。T(n) = T(n - 1) + T(n - 2) + T(n - 3) + T(n - 4)数列の出発点となる最初の4つの初期値は {0, 1, 1, 2} です。これ以降の項は、直前の4項の和として順次決まっていきます。アルゴリズムテトラナッチ数列を
-
C++でトリボナッチ数を生成する方法を解説
トリボナッチ数とはトリボナッチ数(Tribonacci数)は、有名なフィボナッチ数とよく似た数列ですが、フィボナッチ数が直前の2項を足して次の項を求めるのに対し、トリボナッチ数は直前の3つの項を加算して新しい項を生成する点が異なります。n番目の項 T(n) を求める漸化式は以下の通りです。T(n) = T(n - 1) + T(n - 2) + T(n - 3)数列の最初の3項は {0, 1, 1} から始まります。したがって、数列は「0, 1, 1, 2, 4, 7, 13, ...」と続いていきます。アルゴリズムトリボナッチ数を生成する基本的なアルゴリズムは以下のようになります。初期値3つ
-
C++でトリボナッチ語(Tribonacci Word)を生成する方法を解説
トリボナッチ語(Tribonacci Word)とは、数字の並びから構成される文字列のことです。フィボナッチ語(Fibonacci Word)によく似た概念ですが、トリボナッチ語は直前の3つの文字列を順に連結していく点が大きな特徴です。トリボナッチ語の定義トリボナッチ語は、次の漸化式によって定義されます。T(n) = T(n - 1) + T(n - 2) + T(n - 3)最初の3つの文字列は {1, 12, 1213} です。したがって、4番目の文字列は「1213 + 12 + 1」を連結した 1213121 となります。アルゴリズムトリボナッチ語を生成する基本的な手順は以下の通りです。
-
C++で解く行列連鎖乗算問題 ― O(N^3)の動的計画法アルゴリズム
複数の行列の連鎖が与えられたとき、スカラー乗算の回数が最小になる正しい掛け合わせ順序を見つける必要があります。 行列の乗算は結合法則が成り立つため、4つの行列ABCDに対して、A(BCD)、(AB)(CD)、(ABC)D、A(BC)D といった複数の順序で掛け合わせることが可能です。これらの順序の中から、計算コストが最も小さい効率的な順序を見つけることが、この問題の目的です。 入力として、行列の次元を格納した配列arrが与えられます。例えば arr[] = {1, 2, 3, 4} の場合、これは (1×2)、(2×3)、(3×4) の3つの行列が存在することを意味します。 入力 − 入力行
-
C++でペアの最大長チェーンを求める方法(動的計画法)
問題の概要ペアのチェーンが与えられます。各ペアは2つの整数から構成されており、最初の整数は必ず2番目の整数より小さくなっています。チェーンの構築にも同じルールが適用され、ペア (x, y) をペア (p, q) の後に連結できるのは、q < x が成り立つ場合のみです。この問題は、最長増加部分列(LIS)と同じ考え方を応用した動的計画法で効率的に解くことができます。解法の手順は以下のとおりです。与えられたペアを、最初の要素の昇順にソートします。各ペアについて、それ以前のペアの2番目の要素と比較します。arr[i].a > arr[j].b が成り立つ場合、ペア j のチェーンの末尾
-
C++で道路を横断するために必要な最小限の初期エネルギーを求めるアルゴリズム
正の数と負の数が格納された配列を考えてみましょう。この配列は、道路の一方の端からもう一方の端までにあるチェックポイント(中間地点)を表しています。正の値はその地点でエネルギーが増えることを、負の値はエネルギーが減ることを意味します。ここでの課題は、移動中にエネルギーレベルが決して0以下にならないようにするために、出発時に最低どれだけのエネルギーを持っていればよいのか(最小初期エネルギー)を求めることです。 例として、配列 A = {4, -6, 2, 3} の場合を考えてみます。初期エネルギーを0として出発すると、最初のチェックポイントに到達した時点でエネルギーは4になります。しかし、次のチ