-
Pythonでバイナリ文字列として与えられたスコアからゲームの勝者を判定する方法
バレーボールの試合スコアを表すバイナリ文字列が与えられたとき、次のルールに基づいて試合の勝者を判定する方法を解説します。 ゲームのルール 15点先取制: 2チームが対戦し、先に15点を獲得したチームが勝者となります。ただし、両チームが14点に到達した場合はこの限りではありません。 デュースのルール: 両チームが14点に達した場合(デュース)、そこから2点のリードを奪ったチームが勝者となります。 バイナリ文字列において、「0」は注目しているチームがポイントを失ったこと(相手チームの得点)を、「1」は注目しているチームがポイントを獲得したことを表します。この文字列をもとに、そのチームが試合
-
Pythonでオイラー回路を構成するために追加すべき最小の辺数を求めるアルゴリズム
問題概要 オイラー回路(Euler Circuit)とは、グラフ上のすべての辺をちょうど1回ずつ通過し、最終的に出発点へ戻ることができる閉路のことです。 ここでは、b 個のノードと a 本の辺からなる無向グラフが与えられたとき、このグラフにオイラー回路を構成するために追加すべき最小の辺数を求める問題を考えます。 たとえば、次のようなグラフが入力として与えられた場合を考えてみましょう。 この場合、答えは 1 となります。 解法のポイント:オイラー回路の成立条件 連結グラフがオイラー回路を持つための必要十分条件は、すべての頂点の次数(接続されている辺の数)が偶数であることです。したがって、この
-
Pythonで3つの異なる配列から「a + b + c = sum」となる要素の組み合わせを見つける方法
問題の概要3つの配列 A、B、C と、目標値「sum」が与えられたとします。このとき、a + b + c = sum を満たす3つの要素 a、b、c が存在するかどうかを判定します。重要な条件として、a、b、c はそれぞれ異なる配列から選ばれる必要があります。例えば、入力が A = [2,3,4,5,6]、B = [3,4,7,2,3]、C = [4,3,5,6,7]、sum = 12 の場合、出力は True になります。これは 4 + 2 + 6 = 12 が成立し、4、2、6 をそれぞれ A、B、C から取り出せるためです。解法のアプローチこの問題は、すべての組み合わせを総当たり(ブルー
-
PythonでGCDを大きくするために必要な配列からの最小削除数を求めるアルゴリズム
N個の整数で構成されるリストが与えられ、残りの数値のGCD(最大公約数)が、元のN個すべてのGCDよりも大きくなるようにするには、最低何個の数値を取り除けばよいでしょうか。この記事では、その最小削除数を効率よく求めるアルゴリズムをPythonで解説します。 たとえば、入力が [6, 9, 15, 30] の場合、出力は 2 になります。初期のGCDは 3 ですが、6 と 9 を削除すると残りは 15 だけとなり、GCDは 15。これは 15 > 3 を満たすためです。 解法のポイント まず配列全体のGCDを g として求め、各要素を g で割って正規化します。正規化後の配列全体のGCDは
-
Pythonで配列内のnCr値が最大となるペアを検索する方法
問題概要 n個の整数を含む配列arrが与えられたとき、配列からarr[i]とarr[j]を選び、二項係数arr[i]Carr[j](組み合わせの数)が最大になるようなペアを見つける必要があります。条件を満たすペアが複数存在する場合は、そのうちのどれか1つを返せば構いません。 例えば、入力が[4, 1, 2]の場合、出力は「4 2」になります。これは、4C1 = 4、4C2 = 6、2C1 = 2と計算でき、(4, 2)のペアが最大値6を与える唯一の組み合わせだからです。 解法の考え方 この問題を効率的に解くには、二項係数の重要な性質を利用します。nCrは、rがn/2に最も近いときに最大値を取る
-
Pythonで二分木における最大の完全部分木を見つける方法
問題の概要 二分木が与えられたとき、その木の中に含まれる最大の完全部分木(コンプリート・サブツリー)のサイズを求めることを考えます。 ここでいう完全二分木とは、最下層を除くすべてのレベルがノードで完全に埋め尽くされており、最下層のノードは可能な限り左側に配置されている二分木のことです。 たとえば、次のような二分木が入力された場合を考えてみます。 このとき出力されるサイズは 4 となり、最大の完全部分木を通りがけ順(中順)で走査すると 10, 45, 60, 70, の順に出力されます。 解き方のアプローチ この問題は、木を再帰的にたどりながら、各部分木が「完全(complete)」であるか「
-
Pythonで桁を削除して作れる最大の立方数(完全立方数)を求めるアルゴリズム
ある数 N が与えられたとき、その数からできるだけ少ない桁(0桁でも可)を削除して作ることができる、最大の立方数(完全立方数)を求める問題を考えます。与えられた数からは、任意の桁を自由に削除できます。ここで、ある整数 M に対して N = M³ と表せる場合、N を立方数と呼びます。 例えば、入力が 806 の場合、出力は 8 になります。「0」と「6」を削除すれば「8」が残り、8 は 2 の 3 乗(2³ = 8)という立方数だからです。 解法のアプローチ この問題は、次の手順で解くことができます。 preProcess() 関数を定義する:引数として n を受け取ります。 空のリスト t
-
PythonでO(1)空間・O(N²)時間計算量によるバランスの取れた括弧の判定方法
文字列 str に括弧「(」「)」「{」「}」「[」「]」が含まれているとします。このとき、これらの括弧がバランスしているかどうかを判定する必要があります。括弧がバランスしているとは、開き括弧と閉じ括弧が同じ種類で正しく対応しており、正しい順序で閉じられている状態を指します。 例えば、入力が {([])} の場合、出力は True になります。 解法のアプローチ この問題を解くために、以下の手順に従います。 カウンタ cnt を 0、インデックス i を 0、j を -1 で初期化します 関数 solve() を定義します。引数として s と temp を受け取ります solve() 内では
-
Pythonで二分木が赤黒木と同じように高さバランスされているかを判定する方法
問題の概要赤黒木(Red-Black Tree)には「任意のノードにおける最大の高さは、最小の高さの2倍を超えない」という重要な性質があります。この性質を一般の二分探索木に適用し、次の条件が成り立つかどうかを確認することを考えます。すべてのノードについて、そのノードから葉までの最長経路の長さが、最短経路上のノード数の2倍以下であること。たとえば、次のような木が入力として与えられた場合、この木はバランスが取れているため、出力は True になります。解法のアプローチこの問題は再帰的に解くことができます。手順は以下の通りです。関数 solve() を定義します。引数は root(現在のノード)、m
-
Pythonで二分木がヒープ(最大ヒープ)かどうかを判定する方法
この記事では、与えられた二分木がヒープ(最大ヒープ)であるかどうかをPythonで判定するアルゴリズムを解説します。再帰処理を使って「完全二分木であること」と「親子間の大小関係」を効率的にチェックする方法を、実装例とともに見ていきましょう。 ヒープの条件とは? ある二分木がヒープとみなされるためには、次の2つの性質を満たしている必要があります。 完全二分木であること:最後のレベルを除くすべての階層がノードで埋まっている状態になっている 最大ヒープの性質を持つこと:すべての親ノードの値が、その子ノードの値以上である たとえば、次のような木構造が入力として与えられた場合、これらの条件をすべて
-
Pythonで文字列が有効な数値かどうかを判定する方法
数値や小数点を含む文字列が与えられたとき、その文字列が実際に数値として有効かどうかを判定する方法を解説します。例えば、入力が「2.5」であれば結果は True となり、「xyz」のような文字列であれば False となります。解決のアプローチこの問題を解決するには、以下の手順に従います。プログラミング言語が持つ文字列パース(型変換)の仕組みを利用します。文字列を数値に変換しようと試みます。変換が成功して例外が発生しなければ、その文字列は数値として有効です。逆に、変換時に例外(ValueError など)が発生した場合は、数値ではないと判断できます。実装例以下のコードは、float() 関数と例
-
Pythonで配列のサイズkのすべてのセグメントにキーが存在するか確認する方法
問題の概要N個の要素を持つ配列A、探索対象の値p、そしてセグメントサイズkが与えられます。このとき、配列Aをサイズkごとのセグメントに区切った場合に、すべてのセグメントにキーpが含まれているかどうかを判定するのが目的です。たとえば、入力が次のとおりだったとします。A = [4, 6, 3, 5, 10, 4, 2, 8, 4, 12, 13, 4]p = 4k = 3この場合、配列は [4, 6, 3]、[5, 10, 4]、[2, 8, 4]、[12, 13, 4] の4つのセグメントに分けられ、それぞれに値4が含まれているため、出力は True になります。アルゴリズムの手順この問題は、以
-
Pythonで無限チェス盤上のN個のナイト配置からキングがチェックメイトかどうかを判定する方法
問題の概要 通常のチェスと同じルールが適用される無限チェス盤を考えます。盤上には N 個のナイト(騎士)が配置されており、これらの座標とキングの座標が与えられたとき、そのキングがチェックメイトの状態にあるかどうかを判定します。盤面が無限であるため、座標は非常に大きな値になる可能性があります(−109 ≤ x, y ≤ 109)。 たとえば、次のような入力が与えられたとします。 ナイトの位置:[[2,1], [1,3], [3,6], [5,5], [6,1], [7,3]] キングの位置:[4,3] この場合、キングには安全な移動先が一切存在しないため、出力は True(チェックメイト)
-
Pythonで数がトロイ数(Trojan Number)かどうかを判定する方法
ある数 n が与えられたとき、それが「トロイ数(Trojan Number)」であるかどうかを判定します。トロイ数とは、「強い数(Strong Number)」であるにもかかわらず、累乗数(perfect power)ではない数のことを指します。ここで、数 n が強い数であるとは、n のすべての素因数 p に対して p² もまた n の約数となることを意味します。言い換えると、すべての素因数が少なくとも2回現れる数です。トロイ数は必ず強い数ですが、その逆は成り立ちません。つまり、すべての強い数がトロイ数というわけではなく、ab の形で表せないものだけがトロイ数となります。たとえば入力が 72
-
Pythonで数値がアキレス数かどうかを判定する方法
ある整数 n が与えられたとき、その数がアキレス数(Achilles number)であるかどうかを判定しましょう。アキレス数とは、「べき乗数(powerful number)」であるにもかかわらず「完全累乗数」ではない数のことです。べき乗数とは、すべての素因数 p に対して p² もその数を割り切るような数 N を指します。一方、完全累乗数とは、mk(k ≥ 2)の形で表される数(例:平方数、立方数など)です。なお、アキレス数という名前はギリシャ神話の英雄アキレスにちなんだもので、「強力でありながら完全ではない」という「アキレスのかかと」の故事に由来しています。アキレス数の例としては、72、
-
Pythonで数値が素数階乗素数(プライモリアル素数)かどうかを判定する方法
ある数 n が与えられたとき、その n が「素数階乗素数(primorial prime)」であるかどうかを判定することを考えます。素数階乗素数とは、pN# + 1 または pN# − 1 の形で表される素数のことです。ここで pN# は pN の素数階乗(primorial)を表し、「最初の N 個の素数の積」として定義されます。 例えば、入力が 29 の場合、出力は True になります。N = 3 のとき素数階乗は 2 × 3 × 5 = 30 となり、30 − 1 = 29 であるため、29 は pN# − 1 の形の素数階乗素数に該当します。 なお、素数階乗素数の具体例としては、5
-
C++ STLのヒープ操作徹底解説:make_heap・push_heap・pop_heap・sort_heap・is_heapの使い方
C++ STLには、ヒープ(heap)データ構造を扱うための便利な関数群が用意されています。ヒープを利用すると要素を高速に挿入でき、取り出し操作では常に残りの要素の中で最大の値が得られます。最大値以外の要素の並び順は実装に依存します。本記事では、STLが提供する主要なヒープ操作関数を、サンプルコードと実行結果とともにわかりやすく解説します。 make_heap() ― 範囲をヒープ化する make_heap() は、コンテナ内の指定した範囲をヒープ構造に変換する関数です。また、front() を使うことで、ヒープの先頭要素(最大値)を参照できます。 サンプルコード #include <
-
Pythonで後順走査(ポストオーダー)の結果から二分探索木を構築する方法
二分探索木(BST)の後順走査(ポストオーダー走査)の結果が与えられたとき、そのシーケンスから元の木を復元する方法を解説します。例えば、後順走査の結果が [9,15,7,20,3] である場合、構築される木は次のようになります。基本となる考え方通常、木を一意に復元するには中順走査(インオーダー走査)の結果も必要です。しかし、二分探索木では中順走査の結果が必ず昇順にソートされた順序になるという重要な性質があります。この性質を利用すれば、後順走査の結果だけで木を構築できます。アルゴリズムの手順中順走査のリスト = 後順走査のリストをソートしたもの として求めるbuild_tree() メソッドを定
-
Pythonで中順・後順走査の結果から二分木を再構築する方法
二分木の中順走査(inorder)と後順走査(postorder)の結果が与えられているとします。これらの走査結果をもとに、元の二分木を復元することを考えます。たとえば、後順走査が [9,15,7,20,3]、中順走査が [9,3,15,20,7] の場合、構築される木は次の図のようになります。 この問題を解く鍵は、後順走査の最後の要素が必ず木のルートになるという性質です。さらに、中順走査においてそのルートより左側にある要素は左部分木に、右側にある要素は右部分木に属します。この性質を再帰的に適用することで、木全体を組み立てることができます。 アルゴリズムの手順 build_tree() メ
-
Pythonのスタックを使って後順走査(ポストオーダー)から二分探索木(BST)を構築する方法
問題概要 二分探索木(BST)の後順走査(ポストオーダートラバーサル)の結果が1つ与えられたとき、その走査結果から元となる二分探索木を復元する問題を考えます。 例えば、入力が [6, 12, 10, 55, 45, 15] の場合、出力される木構造は次のようになります。 解法のアプローチ この問題を解くために、以下の手順に従います。 関数 solve() を定義します。引数として後順走査のリスト postorder を受け取ります。 n := postorder の要素数とします。 root := 後順走査の最後の要素を値として持つ新しいツリーノードを作成します。 stk := 空のスタッ