-
【C++】奇数をすべて削除した範囲[1, n]におけるk番目に小さい数の求め方
問題の概要この問題では、2つの整数 n と k が与えられます。求めるのは、範囲 [1, n] からすべての奇数を削除した状態で、k番目に小さい数を見つけることです。つまり、偶数のみが残った範囲 [1, n] の中で、k番目に小さい値を特定する必要があります。例えば、範囲 [1, 5] の場合、残る数は「2」と「4」になります。具体例で理解しよう入力: n = 12, k = 4出力: 8解説:範囲 [1, n] に含まれる偶数は「2, 4, 6, 8, 10, 12」の6個です。この中で4番目に小さい要素は 8 となります。解法のアプローチこの解法は非常にシンプルです。n までの偶数の中から
-
C++でx^yとy^xのどちらが大きいかを判定する方法
この問題では、2つの数値 x と y が与えられ、x^y と y^x のうち大きい方を求めることが課題となります。 問題の概要 問題は非常にシンプルです。「x の y 乗」と「y の x 乗」を計算し、どちらの値が大きいかを判定します。 入出力例 入力: x = 4, y = 5 出力: 1024 説明: x^y = 4^5 = 1024y^x = 5^4 = 625 したがって、大きい方の値は 1024 となります。 解法のアプローチ 最も素直な解法は、x^y と y^x の値をそのまま計算して比較することです。しかし、x や y が大きくなると累乗の値が急激に巨大化し、オーバーフローを起こ
-
【C++】同じ数字の組み合わせで作れる「Nより小さい最大の数」を求めるアルゴリズム
問題の概要 この問題では、ある数値を表す文字列 N が与えられます。求めるのは、N を構成するすべての桁の数字を使い、なおかつ N より小さくなる数のうち最大のものです。 入出力の例 入力: N = 54314 出力: 54143 「54314」の各桁(5, 4, 3, 1, 4)を並べ替えて作れる数のうち、54314 未満で最大なのは「54143」です。 解法のアプローチ この問題の基本的な考え方は、「どの桁を入れ替えれば N より小さい最大の数になるか」を見つけることです。ここで重要なのは、ある桁がその左隣の桁より小さい場合、その位置で並べ替えを行うと必ず元の数より小さい数が作れるとい
-
C++で二分木における最大部分木の合計を求める方法
この問題では、二分木(バイナリツリー)が与えられます。私たちのタスクは、木の中で最も大きな合計値を持つ部分木を見つけることです。 問題の概要 二分木には正の値と負の値が混在しています。その中から、ノードの合計が最大になる部分木を特定する必要があります。 例で問題を理解しよう 出力: 13 説明: 左部分木の合計:7 右部分木の合計:1 木全体の合計:13 このように、根を含む木全体の合計である「13」が最大の部分木の合計となります。 解法のアプローチ この問題を解くためには、後順走査(ポストオーダー走査)を利用します。手順は以下の通りです。 左部分木と右部分木それぞれのノードの合計を再
-
C++でnの約数のうち桁和が最大となる値を求めるアルゴリズム
この記事では、整数 n が与えられたときに、n のすべての約数の中で桁の合計(桁和)が最大となる値を求める問題を解説します。基本的な O(n) の解法から、√n を活用した効率的な O(√n) の解法まで、C++ のサンプルコードとともに見ていきましょう。 問題の概要 与えられた整数 n の約数をすべて列挙し、それぞれの桁和を計算します。そして、その中で最も大きな桁和を答えとして返すのが目的です。 入出力例 入力: 18 出力: 9 解説: 18 の約数は 1, 2, 3, 6, 9, 18 です。それぞれの桁和を計算すると、1, 2, 3, 6, 9, 9 となり、最大値は 9 であるこ
-
C++で巨大な数のa^bの最後の桁を効率的に求める方法
この問題では、2つの数 a と b が与えられ、巨大な数になる a^b の最後の桁(下一桁)を求めることが課題となります。a^b は桁あふれするほど大きな値になる可能性があるため、べき乗を直接計算するのではなく、工夫された方法で下一桁だけを導き出します。 問題の例 入力: a = 4、b = 124 出力: 6 解説: a^b の実際の値は 4.523128486 × 1074 という莫大な数ですが、その最後の桁は「6」です。 解法のアプローチ この問題を解くカギとなるのは、「ある数の冪乗の下一桁は、指数が4回ごとに同じパターンで循環する」という性質です。 さらに、冪乗の最後の桁は底の最後
-
C++で数値の5乗の下5桁を効率的に求める方法
この記事では、C++を使って「与えられた5桁の数値を5乗した結果の下5桁」を求める方法を解説します。 問題の概要 整数 N が与えられたとき、N を5乗した値のうち、最後の5桁(下5桁)だけを出力するのが課題です。巨大な数をそのまま計算するとオーバーフローのリスクがあるため、工夫が必要になります。 入力例:N = 25211 出力例:25211 の5乗の下5桁 解法のアプローチ 必要なのは結果の下5桁だけなので、毎回の乗算後に 100000 で割った余り(剰余) を取ることで、常に5桁以内の値を保持できます。これは数学的に正しい方法です。なぜなら、積の下5桁は各因数の下5桁だけで決まるためです
-
C++で正六角形の対角線の長さを求める方法
この問題では、正六角形の一辺の長さを表す整数 n が与えられます。私たちの課題は、その正六角形の対角線の長さを求めることです。問題の概要ここでは、正六角形の一辺の長さが与えられ、その六角形の対角線の長さを計算する必要があります。具体例で理解しよう入力: a = 7出力: 12.11解き方のアプローチこの問題は、次の数学的な公式を使うことで簡単に解くことができます。対角線 = 1.73 × a公式の導出過程一辺の長さが a の正多角形(正六角形)を考えます。対角線と辺がなす角度は 60° です。(d/2) と a の比は sin 60° に等しくなります。sin 60° = d / (2 × a
-
C++で連結リストのループ(循環部分)の長さを求める方法
この記事では、ループ(循環)を含む可能性がある連結リストが与えられたときに、そのループの長さ(ループ内のノード数)を求める方法を解説します。 問題の概要 与えられた連結リストにループが存在する場合は、ループを構成するノードの数を数えて返します。ループが存在しない場合は -1 を返します。 具体例を見てみましょう。 入力: 連結リスト:1 → 2 → 3 → 4 → 5 → 6 → 7 → 2(ノード2に戻る) 出力: 6 この例では、ノード7の次がノード2に接続されており、ノード2からノード7までの6個のノードがループを形成しています。 解決アプローチ:フロイドの循環検出法 まず、連結リス
-
C++でブール行列における最大領域のサイズを求める方法
はじめに この記事では、0と1のみで構成される n×m の2次元行列(ブール行列)が与えられたとき、その中で最も大きな「領域」のサイズを求める方法を解説します。 問題の概要 値が 1 のセルは「塗りつぶしセル」とみなされます。塗りつぶしセル同士が水平方向・垂直方向・斜め方向のいずれかで隣接している場合、それらは同じ領域に属すると判断します。私たちのタスクは、こうして連結したセルの数が最大となる領域の大きさ(セル数)を求めることです。 具体例で理解しよう 入力: matrix[4][5] { {0, 1, 1, 0, 1}, {0, 0, 1, 1, 1}, {1, 0, 0, 0,
-
C++のビット演算を使ってアルファベットの文字位置を求める方法
この記事では、英字で構成された文字列 str が与えられたとき、ビット演算を使って各文字がアルファベットの何番目に位置するかを求める方法を解説します。問題の概要文字列内の各文字について、英語アルファベットにおける位置(1〜26)を出力します。文字の大小は区別せず、「t」と「T」は同じ文字として扱います。入出力例入力: str = Tutorialspoint出力: 20 21 20 15 18 9 1 12 19 16 15 9 14 20解法のアプローチ文字の位置を求める最もシンプルな方法は、各文字と31の論理積(AND)を取ることです。ASCIIコードでは「A」が65、「a」が97であり、
-
C++で文字列内の最も長い数値を検索する方法
問題の概要この問題では、文字と英字のみで構成される文字列 str が与えられます。私たちのタスクは、文字列内で最も桁数の多い数値を見つけることです。問題の詳細: 文字列内に含まれる連続した数字の並び(数値)の中から、最も桁数が大きいものを特定する必要があります。具体例で問題を理解しよう入力: str = code001tutorials34124point出力: 34124説明:この文字列に含まれる数値は以下の通りです。001 → 桁数 334124 → 桁数 5このうち最も桁数が多いのは「34124」であるため、これが答えとなります。解決アプローチこの問題に対するシンプルな解決策は、文字列を
-
【C++】デジタルルート(繰り返し桁和)がNとなるM番目の数を求める方法
問題概要この問題では、2つの正の整数 N と M が与えられます。求めるのは、「ある数の各桁の和を繰り返し計算して1桁になるまで処理した結果(デジタルルート)が N と等しくなる」ような数のうち、M番目の数です。例えば、入力として N = 4、M = 6 が与えられた場合、出力は 49 となります。その理由を見てみましょう。49 の各桁の和は 4 + 9 = 13、さらに 1 + 3 = 4 となり、最終的に 4 になります。デジタルルートが 4 となる数は 4, 13, 22, 31, 40, 49 … と公差 9 で続いていくため、6番目の数は 49 となるのです。解法アプローチ最も単純な
-
C++でk個のソート済み配列からm番目に小さい値を効率的に求める方法
この問題では、サイズの異なるk個の配列が与えられます。目的は、k個のソート済み配列全体の中からm番目に小さい値を見つけることです。 問題の概要 すべての配列を1つにマージしたと仮定したとき、その中でm番目に小さい要素を求めます。 入出力例 入力: m = 4 arr[][] = { {4, 7}, {2, 5, 6}, {3, 9, 12, 15, 19} } 出力: 5 解説: すべての配列をマージしてソートすると「2, 3, 4, 5, 6, 7, 9, 12, 15, 19」となり、4番目の要素は5であることがわかります。 解法アプローチ シンプルな解法:マージしてソートする
-
C++で最初のn個の自然数のm番目の合計を求める方法
問題概要 この記事では、2つの整数 m と n が与えられたときに、最初のn個の自然数のm番目の合計を求める方法を解説します。 ここでいう「m番目の合計」とは、n個の自然数の合計をm回繰り返し計算する操作のことです。合計は次の漸化式で定義されます。 m > 1 の場合: sum(n, m) = sum( sum(n, m-1), 1 ) m = 1 の場合: sum(n, 1) = n個の自然数の合計 = n × (n + 1) / 2 入出力例 入力: m = 4、n = 2 出力: 231 計算過程: sum(2, 4) = sum( sum(2, 3), 1 )
-
C++で2つの有理数のうち大きい方(最大値)を求める方法
問題概要この問題では、2つの有理数が与えられ、そのうち大きい方(最大値)を見つけることが課題となります。ここで扱う有理数は、p/q の形式(分数形式)で表されるものとします。具体例で問題を理解しよう入力:rat1 = 5/4、rat2 = 3/2出力:3/2説明:5/4 = 1.253/2 = 1.5小数に変換して比較すると、1.5 の方が大きいため、答えは 3/2 となります。解法のアプローチこの問題は、学校の数学で習った方法と同じ考え方で解くことができます。手順は以下の通りです。まず、2つの分母の最小公倍数(L.C.M.)を求めます。次に、各分数の分子を、分母を最小公倍数に揃えるために必要
-
C++で二分木の最大値(または最小値)を求める方法
この記事では、二分木が与えられたときに、その中から最大値(または最小値)を持つノードを見つける方法を解説します。 問題の概要 与えられた二分木の中から、最大値および最小値を持つノードの値を求めるのが課題です。 入力例 出力例 max = 9 , min = 1 解法のアプローチ 二分木の最大値を求めるには、木全体を走査する必要があります。基本的な考え方は次のとおりです。 ルートノードから出発し、再帰的に左部分木と右部分木を走査します。 各ノードにおいて、そのノードの値・左部分木の最大値・右部分木の最大値を比較します。 最も大きい値を現在の最大値として返し、再帰的に結果を親ノードへ伝えてい
-
C++でサイズkの部分配列の最大(最小)合計を効率的に求める方法
この記事では、配列 arr[] と整数 k が与えられたときに、サイズ k の部分配列(連続する要素)の合計の最大値(または最小値)を求める問題を解説します。問題の例入力:arr[] = {55, 43, 12, 76, 89, 25, 99}、k = 2出力:165説明:サイズ2の部分配列の中では、{76, 89} の合計である 76 + 89 = 165 が最大となります。解法アプローチ1. 全探索(単純なアプローチ)最も単純な方法は、サイズ k のすべての部分配列を列挙し、それぞれの合計を計算して最大値を返すことです。ただし、この方法の計算量は O(n×k) となるため、配列が大きい場合
-
C++で二分木のすべての右ノードから最大値を見つける方法
この記事では、二分木(バイナリツリー)が与えられたときに、すべての右ノードの中から最大値を見つける方法を解説します。問題の概要与えられた二分木に含まれるすべての「右の子ノード」の値を調べ、その中で最大の値を求めるのが目的です。入力例以下のような二分木を考えてみましょう。 5 / \ 3 2 / \ / \ 1 8 6 9出力例9解説この木における右の子ノードは {2, 8, 9} の3つです。これらの中で最大の値は 9 となります。解決アプローチこの問題は、木を再帰的に走査しながら解くことができます。基本的な考え方は以下のとおり
-
C++でx^(y^2)とy^(x^2)のどちらが大きいかを判定する方法
問題概要 この問題では、2つの整数 x と y が与えられ、x^(y^2) と y^(x^2) のうち大きい方を求めることが課題となります。 具体例で理解しよう 入力:x = 4、y = 3 出力:3^(4^2) 説明: x^(y^2) = 4^(3^2) = 4^9 = 262144 y^(x^2) = 3^(4^2) = 3^16 = 43046721 基数が小さい方の式が大きくなるという、一見すると直感に反する興味深い結果です。 解法アプローチ 最も素朴な方法は、両方の値を実際に計算してから大きい方を出力することです。しかし、指数が大きくなると結果が爆発的に増大し、標準のデータ型では