-
Pythonで文字列リストの最長共通プレフィックス(接頭辞)を求めるプログラム
小文字で構成された文字列のリストが与えられたとき、その中に共通して含まれる最長の共通プレフィックス(接頭辞)を見つける問題を考えてみましょう。例えば、入力が [antivirus, anticlockwise, antigravity] の場合、すべての文字列に共通する先頭部分は anti なので、出力は anti となります。解決のためのアプローチこの問題は、以下の手順で解くことができます。まず、リスト words をアルファベット順にソートします。これにより、辞書順で最も近い文字列同士が隣り合うため、比較が効率的になります。共通プレフィックスを格納するための新しいリスト prefix を用
-
Pythonで同じ文字が連続する最長部分文字列の長さを求めるプログラム
この記事では、Pythonを使って「同じ文字が連続している最長の部分文字列の長さ」を求める方法を解説します。 例えば、入力が abbbaccabbbba の場合、b が4つ連続して並んでいる箇所があるため、出力は 4 となります。 解法のアプローチ この問題は、文字列を先頭から順番に走査し、隣接する2つの文字を比較することで解決できます。具体的な手順は以下のとおりです。 文字列 s の長さが 0 の場合は、そのまま 0 を返します。 s の末尾に空白文字を1つ追加します。これは、ループ処理の際に文字列の最後にある連続グループも確実に確定させるためのテクニックです。 カウンター ct と一時
-
Pythonで文字を入れ替えて、同じ長さの2つの文字列を等しくできるか判定する方法
問題の概要長さnの2つの文字列 s と t があるとします。s から1文字、t から1文字を選んで入れ替える(スワップする)操作は何度でも行えます。このとき、2つの文字列を完全に等しくすることが可能かどうかを判定するのが課題です。例えば、入力が s = xy、t = yx の場合、出力は True になります。解法のアプローチこの問題は、次の手順で解くことができます。s と t を連結した文字列 st を作成し、ソートします。st の先頭から2文字ずつペアとして確認します(インデックス0から開始し、2ずつ増やしながらループ)。st[i] と st[i+1] が異なる場合は、False を返しま
-
Pythonで1つの要素を削除して作れる最長の連続増加サブリストの長さを求める方法
問題の概要 数値のリスト nums が与えられます。ここで、リストから0個または1個の要素を削除できるものとし、その結果として得られる「連続した厳密に増加する部分リスト(サブリスト)」の最大の長さを求めます。 たとえば、入力が nums = [30, 11, 12, 13, 14, 15, 18, 17, 32] の場合、答えは 7 になります。18 を削除すれば [11, 12, 13, 14, 15, 17, 32] という最も長い連続した厳密増加部分リストが得られ、その長さがちょうど 7 になるためです。 解法の考え方 この問題は、次の2つの配列を用意すると効率よく解けます。 pre
-
Pythonで文字列から作れる「pizza」の個数を数えるプログラム
問題概要 小文字のみで構成された文字列 s が与えられたとき、その中に含まれる文字を使って、何個の「pizza」という文字列を作ることができるかを求める問題です。 文字は任意の順序で使用できますが、同じ文字を複数回使うことはできません(ある「pizza」を作るために使った文字は、別の「pizza」には使えません)。 例えば、入力が ihzapezlzzilaop の場合、出力は 2 になります。 「pizza」1個を作るのに必要な文字:p × 1、i × 1、z × 2、a × 1 この文字列には p が2個、i が2個、z が3個、a が2個含まれているため、最大2個の「pizza」が作れ
-
Pythonでリスト内の2つの異なる要素から最大の積を求めるプログラム
はじめに数値のリストが与えられたとき、その中から異なる2つの要素を選び、その積(掛け算の結果)の最大値を求める問題を考えてみましょう。例えば、入力が [5, 3, 7, 4] の場合を考えます。このとき最大の積は 7 × 5 = 35 となります。解き方のアプローチ最もシンプルな方法は、全ての要素ペアの組み合わせを調べる総当たり(ブルートフォース)による解法です。手順は以下の通りです。現在の最大値を保持する変数 curr_max を負の無限大(-inf)で初期化します。外側のループでインデックス i を 0 から要素数 - 1 まで回します。内側のループでインデックス j を i + 1 から
-
Pythonで中央値の絶対差が最小になるように数値リストを分割する方法
数値のリスト nums が与えられたとき、それを同じサイズの2つのグループに分割し、それぞれのグループの中央値の絶対差ができるだけ小さくなるようにすることを考えます。そして、その最小の差を求めるのがこの問題の目的です。なお、リストの長さを2で割った値(len(nums) / 2)は必ず奇数になると仮定します。 問題の例 たとえば、入力が [2, 10, 8, 5, 4, 7] の場合を考えてみましょう。このとき、[2, 5, 10] と [4, 7, 8] という2つのリストに分割できます。それぞれの中央値は 5 と 7 となるため、出力はその差である 2 になります。 解法のアプローチ この
-
Pythonで2つのソート済みリストをマージして1つのソート済みリストを作成する方法
2つのソート済みリスト A と B が与えられたとき、それらをマージして、1つのソート済みリスト C を作成することを考えます。なお、2つのリストのサイズは異なっていても構いません。 例えば、A = [1, 2, 4, 7]、B = [1, 3, 4, 5, 6, 8] の場合、マージ後のリスト C は [1, 1, 2, 3, 4, 4, 5, 6, 7, 8] となります。 アルゴリズムの考え方 この問題は、2つのリストを先頭から順に比較しながら要素を取り出していく「マージ処理」で解くことができます。各リストに対してポインタ(インデックス)を1つずつ用意し、小さい方の要素を結果のリストに追
-
Pythonで数値リストを昇順・降順に並べ替える最小コストを求める方法
問題の概要数値のリスト nums が与えられたとき、そのリストを昇順または降順のいずれかで並べ替えるために必要な最小コストを求めます。ここでいうコストとは、各要素の元の値と新しい値の差(絶対値)の合計のことです。例えば、入力が [2, 5, 4] の場合、出力は 2 になります。解決のアプローチこの問題は、以下の手順で解くことができます。元のリスト nums のコピー temp を作成するtemp を昇順にソートするc1 = 0、c2 = 0 として初期化するn にリストのサイズを代入するi を 0 から n-1 まで繰り返し処理する:nums[i] が temp[i] と異なる場合、c1 に
-
Pythonでリスト内の「出現回数と値が一致する要素」を検索する方法
数値のリスト nums が与えられたとき、「リスト内での出現回数(頻度)が、その要素自身の値と一致する要素」が存在するかどうかを判定する問題を考えてみましょう。たとえば、入力が [2, 4, 8, 10, 4, 4, 4] の場合を考えてみます。このリストでは 4 がちょうど4回出現しているため、条件を満たす要素が存在し、出力は True になります。解決のアプローチこの問題は、以下の手順で解くことができます。まず、各値の出現回数を記録するための辞書(マップ)res を作成します。次に、res 内の各キーと値のペア (k, v) を順番に確認します。キー k(要素の値)と値 v(出現回数)が一
-
Pythonで1からNまでの範囲の欠落している数字をすべて見つけるプログラム
サイズ n の整数リスト nums があり、リスト内のすべての数値は区間 [1, n] に含まれているとします。このとき、一部の要素は2回出現し、その他は1回だけ出現します。この課題では、[1, n] の範囲のうちリストに存在しない数値(欠落している数字)をすべて見つけ、昇順に並べて返す必要があります。できるだけ線形時間 O(n) で動作する効率的な解法を目指しましょう。 例えば、入力が [4, 4, 2, 2, 6, 6] の場合、出力は [1, 3, 5] となります。 解法のアプローチ この問題は「カウント配列(各数値の出現回数を記録する配列)」を使うことでシンプルに解決できます。手順は
-
Pythonで偶数は昇順・奇数は降順に並べ替えるプログラムの書き方
問題の概要 数値のリスト nums が与えられたとき、以下の条件をすべて満たすように配列を並べ替えることを考えます。 偶数は昇順(小さい順)に並べ替える 奇数は降順(大きい順)に並べ替える 偶数と奇数の相対的な位置関係は変更しない 例えば、入力が [9, 14, 12, 91, -4, 5] の場合、出力は [91, -4, 12, 9, 14, 5] となります。 解決のアプローチ この問題は、次の手順で解くことができます。 evens:nums 配列から偶数だけを取り出したリストを作成する odds:nums 配列から奇数だけを取り出したリストを作成する evens リストを昇順に
-
Pythonでナルシスト数(アームストロング数)を判定するプログラムの作成方法
ナルシスト数とは? ナルシスト数(Narcissistic Number、別名:アームストロング数)とは、「各桁の数字を桁数乗して合計した値が、元の数そのものと一致する数」のことです。 例えば、9474 を考えてみましょう。この数は4桁なので、各桁の数字を4乗して足し合わせます。 9^4 + 4^4 + 7^4 + 4^4 = 6561 + 256 + 2401 + 256 = 9474 計算結果が元の数 9474 と一致しているため、9474 はナルシスト数であると言えます。 判定アルゴリズムの手順 この問題を解くためには、以下の手順に従います。 数値 n を文字列に変換し、各桁の数字を
-
Pythonで二分探索木(BST)の指定範囲内にあるノード数を求める方法
問題の概要 二分探索木(BST)が与えられ、さらに左側の境界値 l と右側の境界値 r が指定されます。このとき、木に含まれるすべてのノードの中で、値が l 以上 r 以下の範囲内にあるノードの個数を求めるのが目的です。 例えば、次のような木が与えられたとします。 このとき l = 7、r = 13 とすると、範囲内に含まれるノードは 8、10、12 の3つなので、出力は 3 になります。 アルゴリズムの考え方 スタックを使った反復的な深さ優先探索(DFS)で木をたどります。重要なポイントは、二分探索木の性質を活かして枝刈り(pruning)を行うことです。値が境界より小さいノードの左側の
-
Pythonでn個のルークが互いに攻撃し合わないように配置する方法の数を求めるプログラム
この記事では、n×n のチェス盤に n 個のルークを、互いに攻撃し合わないように配置する方法が何通りあるかを Python で求める方法を解説します。 問題の概要 サイズ n×n のチェス盤があるとします。ここに n 個のルークを、どのルークも他のルークを攻撃できないように配置するとき、その配置方法の総数を求めます。 ルークは同じ行または同じ列にある駒を攻撃できるため、「互いに攻撃し合わない」という条件は「すべてのルークがそれぞれ異なる行・異なる列に存在する」ことを意味します。 また、2つの配置方法は、あるマスが一方の配置では占められていて、もう一方では占められていない場合に「異なる」とみな
-
PythonでN番目のフィボナッチ数を求めるプログラム
数値 n が与えられたとき、n番目のフィボナッチ数を求めるプログラムをPythonで作成してみましょう。フィボナッチ数列とは、i番目の項が f(i) = f(i-1) + f(i-2) という漸化式で定義される数列です。最初の2項は 0 と 1 であり、それ以降の各項は直前の2つの項の和になります。数列を並べると「0, 1, 1, 2, 3, 5, 8, 13, 21, ...」のように続いていきます。例えば、入力が 15 の場合、15番目のフィボナッチ数である 610 が出力されます。解き方の手順この問題は反復処理(ループ)を使うことで効率的に解けます。手順は以下の通りです。変数 first
-
Pythonで整数の2進表現に含まれる1のビット数を数える方法
ある整数 n が与えられたとき、その数を2進数で表した際に含まれる「1」のビット(セットビット)の個数を求めることを考えます。この問題は「ポピュレーションカウント」や「ハミング重み」と呼ばれることもあり、ビット演算の基礎を学ぶのに最適な題材です。問題の例例えば、入力が 12 の場合を考えてみましょう。12 を2進数で表すと 1100 となり、「1」のビットは2個含まれています。したがって、出力は 2 になります。解法のアプローチこの問題は、次の手順で解くことができます。カウンター変数 count を 0 で初期化するn が 0 になるまで以下を繰り返すn の最下位ビット(n AND 1)を c
-
Pythonで二分木内の長さkの一意なパスを数えるプログラム
問題概要 一意な値を持つ二分木と整数 k が与えられます。このとき、木の中に存在する「長さ k の一意なパス」の総数を求めます。パスは親ノードから子ノードへ向かう方向でも、子ノードから親ノードへ向かう方向でも構いません。また、あるノードが片方のパスにのみ含まれる場合、その2つのパスは互いに異なるものとして扱います。 入力例と出力例 たとえば、次のような二分木が与えられたとします。 k = 3 の場合、出力は 4 になります。該当するパスは次の4本です。 [12, 8, 3] [12, 8, 10] [8, 12, 15] [3, 8, 10] 解き方:深さ優先探索(DFS)によるアプ
-
Pythonで1種類の文字だけを含む部分文字列の総数を求めるプログラム
問題の概要小文字の英字のみで構成される文字列 s が与えられたとき、「1種類の文字だけで構成されている部分文字列」の総数を求めます。例えば、入力が xxyy の場合、出力は 6 になります。条件を満たす部分文字列は [x, x, xx, y, y, yy] の6つだからです。解決のアプローチこの問題は、連続して同じ文字が並ぶ区間(ラン)ごとに考えると効率的に解けます。長さ n の同一文字の連続区間から作れる部分文字列の数は n(n+1)/2 個ですが、ループ内で「現在の文字が何文字連続しているか」をカウントしながら合計へ加算していけば、結果的に同じ値が得られます。具体的な手順は次のとおりです。
-
Pythonで最初のn個の奇数の合計を求めるプログラム
数値 n が与えられたとき、最初の n 個の正の奇数の合計を求めることを考えます。たとえば、入力が 7 の場合、出力は 49 になります。これは [1 + 3 + 5 + 7 + 9 + 11 + 13] = 49 となるためです。解決の手順この問題は、以下のステップに従って解くことができます。n が 0 と等しい場合は、0 を返します。変数を初期化します。sum := 1、count := 0、temp := 1count < n - 1 の間、次の処理を繰り返します。temp := temp + 2(次の奇数を生成)sum := sum + temp(合計に加算)count := c