-
Pythonで1つのリストを別のリストへ変換するのに必要なスワップ回数をカウントするプログラム
問題の概要2つの数値リスト L1 と L2 があるとします。各リストの長さは n で、すべての値はリスト内で一意であり、値の範囲は 0 ~ n-1 です。このとき、L1 を L2 に変換するために必要な「隣接要素のスワップ(交換)」の最小回数を求めます。例えば、入力が L1 = [0, 1, 2, 3]、L2 = [2, 0, 1, 3] の場合、出力は 2 になります。まず 1 と 2 を入れ替えると L1 は [0, 2, 1, 3] になり、次に 0 と 2 を入れ替えると L1 は [2, 0, 1, 3] となり、L2 と一致するためです。解決のアプローチこの問題は、以下の手順で解く
-
Pythonで全移動日をカバーするバス乗車券の最低料金を求めるプログラム(動的計画法)
問題の概要 ソート済みの整数リスト days が与えられます。このリストに含まれる各日は、必ずバスで移動しなければならない日を表しています。すべての移動日をカバーするために必要な最低料金を求めましょう。 利用できるバス乗車券は次の3種類です。 1日乗車券:2ドル 7日乗車券:7ドル 30日乗車券:25ドル 入出力の例 たとえば、入力が days = [1, 3, 5, 6, 28] の場合、出力は 9 になります。これは、1日目に7日乗車券(7ドル)を購入して1〜7日目の移動をまとめてカバーし、残りの28日目に1日乗車券(2ドル)を購入すればよいためです。合計は 7 + 2 = 9 ドルと
-
Pythonで文字列として与えられたブール式を評価する方法
「and」や「or」といった論理演算子を含むブール式が、文字列 s として与えられたとします。この式を評価し、その結果を返すのが本記事の目的です。式には括弧が含まれる場合があり、括弧で囲まれた部分は最優先で評価する必要があります。 たとえば、入力が s = T and (F or T) であれば、出力は True になります。 解決の手順 この問題は、スタック(リスト)を活用することで効率的に解けます。全体の流れは以下の通りです。 スタックの初期化:空のリスト stack を用意します。 トークン化:文字列 s を空白区切りで分割し、トークンのリストを作成します。 各トークンの処理:各トー
-
【Python】キャンディー削除ゲームで先手プレイヤーが勝つかどうかを判定するプログラム
問題の概要数値のリスト candies があるとします。あるプレイヤー(player1)が友人(player2)と対戦するゲームを行います。各ターンで、プレイヤーは「同じ値が隣り合っている2つのキャンディー」を選んで取り除くことができます。そして、キャンディーを取り除けなくなった方の負けです。player1が先手であるとき、player1が勝利するかどうかを判定してください。例えば、入力が nums = [2, 2, 5] の場合、出力は True になります。player1が先に「2」のペアを取り除けば、残った [5] からは相手が何も取り除けなくなるためです。解法のアプローチこの問題の鍵と
-
Pythonでローマ数字を整数に変換する方法をわかりやすく解説
ローマ数字で表された文字列を受け取り、それを整数値に変換するプログラムをPythonで作成してみましょう。 ローマ数字は、基本的に大きな値の記号から小さな値の記号へと左から右へ並べられます。ただし、例外的なケースとして「ある記号が1つ小さい値を表す」場合には、小さい記号が大きい記号の前に置かれます(例:IV = 4)。 ローマ数字の各記号と対応する数値 M:1000 D:500 C:100 L:50 X:10 V:5 I:1 たとえば、入力が numeral = MCLXVI の場合、出力は 1166 になります。これは M = 1000、C = 100 で合計1100、続いて L = 5
-
Pythonで最長のボックスチェーンの長さを求めるアルゴリズムと実装方法
問題の概要 ここにボックス(箱)のリストがあるとします。各要素は [start, end] の2つの値を持ち、常に start < end が成り立ちます。あるボックスの「終点」と別のボックスの「始点」が一致する場合、それら2つのボックスをつなげることができます。このとき、形成できるボックスの連鎖(チェーン)のうち、最も長いものの長さを求めるのが目的です。 例として、入力が次のような場合を考えてみましょう。 blocks = [[4, 5], [5, 6], [4, 8], [1, 2], [2, 4]] この場合、出力は 4 になります。これは以下のように4つのボックスで連鎖を作れるた
-
Pythonでコースの開始・終了時刻から受講できる最大コース数を求める方法
この記事では、コースの開始時刻と終了時刻を表す区間リスト [start, end] が与えられたときに、受講できるコースの最大数を求めるPythonプログラムを解説します。条件として、同時に受講できるのは1つのコースのみで、次のコースの開始時刻は直前に受講したコースの終了時刻より後である必要があります。 例えば、入力が times = [[3, 6], [6, 9], [7, 8], [9, 11]] の場合、出力は 3 となります。これは [3, 6]、[7, 8]、[9, 11] の3つのコースを受講できるためです。 解決の手順 この問題は貪欲法(グリーディ法)を使うことで効率的に解けます
-
【Python】2値行列の列を反転して、すべての値が等しくなる行の最大数を求める方法
問題の概要2値行列(各要素が0または1のみで構成される行列)が与えられたとします。この行列に対しては、任意の数の列を選択し、その列に含まれるすべてのセルの値を反転することができます。ここでいう「反転」とは、0を1に、1を0に切り替える操作のことです。このとき、いくつかの列を反転した後、すべての値が等しくなる行の最大数を求めるのがこの問題の目的です。例として、次のような行列を考えてみましょう。000001110この場合の出力は 2 になります。最初の2つの列を反転すると、2行目は「1,1,1」、3行目は「0,0,0」となり、これら2行のすべての値が等しくなるためです。解法のアプローチこの問題を解
-
Pythonで重複文字のない連結文字列の最大の長さを求めるプログラム
問題概要文字列のリスト words が与えられます。ここからいくつかの単語(部分列)を選んで連結し、「すべての文字が一意(重複なし)」となる文字列を作ることを考えます。そのような連結の中で、最も長くなるものの長さを求めるのがこの問題の目的です。例えば、words = ["xyz", "xyw", "wab", "cde"] の場合、答えは 9 になります。「xyz」「wab」「cde」の3つを選んで連結すると「xyzwabcde」となり、x・y・z・w・a・b・c・d・e の9文字がすべて異なるためです。アプローチ
-
Pythonでリスト内の全ペアの連結値の合計を求めるプログラム
数値のリスト nums が与えられたとき、リスト内のすべてのペアについて連結した値の合計を求めることを考えます。ここで重要なのは、ペア (i, j) とペア (j, i) は異なるものとして扱うという点です。問題の例例えば、入力が nums = [5, 3] の場合、出力は 176 になります。考えられる連結は次の4通りです。(nums[0], nums[0]) → 5 と 5 の連結 → 55(nums[0], nums[1]) → 5 と 3 の連結 → 53(nums[1], nums[0]) → 3 と 5 の連結 → 35(nums[1], nums[1]) → 3 と 3 の連結
-
Pythonで各建物の高さをスカイラインを維持したまま最大まで増加させる行列を求めるプログラム
問題の概要 2次元の行列を考えてみましょう。ここで matrix[r][c] は、都市にあるマンション(建物)の高さを表します。東西方向のスカイラインは行列の各行の最大値を取ることで得られ、南北方向のスカイラインは各列の最大値を取ることで得られます。 この記事のゴールは、東西・南北どちらのスカイラインも一切変えずに、各建物の高さを可能な限り最大まで引き上げた新しい行列を作ることです。 入力例 234 567 8910 出力例 444 777 8910 この場合、東西方向のスカイラインは [4, 7, 10]、南北方向のスカイラインは [8, 9, 10] です。1行目のす
-
Pythonで接続して作れる最長スティックの長さを求めるプログラム
整数のリスト sticks があるとします。リストの各要素は両端を持つ1本の棒(スティック)を表しており、各端の値は 1〜6 の範囲に収まっています。2本の棒は、どちらかの端の値が一致していれば連結することができ、連結後の棒の端は「余った側の端」になり、全体の長さは伸びていきます。このとき、作れる中で最も長い棒の長さを求めるのがこの問題の目的です。 たとえば、入力が sticks = [[2, 3], [2, 4], [3, 5], [6, 6]] の場合、出力は 3 になります。[2, 3] と [2, 4] を連結して [3, 4] を作り、さらにそれと [3, 5] を連結することで [
-
Pythonで二分木から「子を1つだけ持つノード」をすべて削除する方法
問題の概要二分木のルートが与えられたとき、子を1つしか持たないノード(左右どちらか片方の子だけを持つノード)をすべて木から取り除くことを考えます。子を2つ持つノードや、子をまったく持たない葉ノードはそのまま残します。例えば、次のような二分木が入力として与えられたとします。この場合、出力は次のようになります。解法のアプローチこの問題は再帰処理を使うことでシンプルに解けます。片方の子しかないノードを見つけたら、そのノードをスキップして子を直接親につなぎ替えるイメージです。具体的には、以下の手順に従います。solve() というメソッドを定義する。引数として木のルートを受け取るroot が null
-
Pythonでライフゲームを実装!セルマトリクスの次の状態を求めるプログラム
問題の概要 2次元のバイナリ行列を考えます。「1」は生存しているセル(生きた細胞)、「0」は死んでいるセルを表します。あるセルの「近傍」とは、そのセルの上下左右および斜め方向に隣接する最大8個のセルのことです。 この記事では、以下のルールに従って行列全体の「次の状態」を求めるプログラムをPythonで実装します。このルールは、数学者ジョン・コンウェイが考案した有名な「ライフゲーム(Conways Game of Life)」と同じものです。 セルの状態遷移ルール 生存しているセルは、隣接する生存セルが2つまたは3つの場合に限り、次の世代でも生存します。 死んでいるセルは、隣接する生存セルが
-
Pythonで2つの数を互いに素でなくするために必要な最小の操作回数を求めるプログラム
2つの整数 A と B が与えられたとします。1回の操作ごとに、どちらか一方の数を選んで 1 増やすか 1 減らすことができます。このとき、A と B の最大公約数(GCD)が 1 以外になる、つまり2つの数が互いに素でなくなるまでに必要な最小の操作回数を求めるのがこの問題です。 たとえば、入力が A = 8、B = 9 の場合、出力は 1 となります。B の 9 を選んで 10 に増やせば、gcd(8, 10) = 2 となり、2つの数は互いに素ではなくなるからです。 解き方の考え方 この問題には重要な性質があります。それは、答えが高々 2 回で足りるということです。2回の操作で両方の数を
-
Pythonでn回の操作(挿入・コピー・ペースト)で入力できる最大文字数を求めるプログラム
問題概要 ある整数 n が与えられたとき、以下の3種類の操作をちょうど n 回行って画面に入力できる最大の文字数を求める問題です。 文字「x」を1つ挿入する 現在表示されているすべての文字をコピーする コピーした内容を貼り付ける(ペーストする) 例えば、入力が n = 12 の場合、出力は 81 になります。 解法のアプローチ この問題は、貪欲法(グリーディ法)を使うことで効率的に解けます。ポイントは、操作の組み合わせによって文字数の増加パターンが周期的に現れることです。 n が小さい場合(n ≤ 4)は、毎回「x」を挿入するだけが最適なので、答えはそのまま n になります。一方、n が
-
Pythonで階段を最後まで登る最小コストを求めるプログラムの実装方法
数値のリスト stairs と整数 k が与えられたとします。現在、私たちは0番目の階段におり、stairs の最後のインデックスにある階段まで登ることが目標です。stairs[i] の値はそのインデックスに到達する際にかかるコストを表し、各ステップで1段から k 段まで任意の段数を一度にジャンプできます。このとき、最後の階段まで登るために必要な最小コストを求めるのがこの問題です。 問題例 例えば、入力が stairs = [4, 11, 11, 3, 2]、k = 3 の場合、出力は 9 になります。これは、コスト [4, 3, 2] の階段を選んで登ることで合計コストを最小化できるためで
-
Pythonで最長の減少単語チェーンの長さを求めるプログラム
有効な単語のリストと文字列 s が与えられたとき、s から始めて1文字ずつ削除しながら、その各段階でも有効な単語になるように辿れる「減少単語チェーン」のうち、最も長いものの長さを求める問題です。たとえば、入力が words = [lii, limit, limi, li, coffee, jug, pool, type]、s = limit の場合、出力は 4 になります。これは「limit」を出発点として、「limit」→「limi」→「lii」→「li」というチェーンが作れるためです。解き方のアプローチこの問題は再帰呼び出しを使うことでシンプルに解けます。基本的な流れは以下のとおりです。s
-
Pythonでnums[i] + nums[j] + (i - j)を最大化するペア(i, j)を見つけるプログラム
問題の概要数値のリスト nums が与えられたとき、i < j を満たすペア (i, j) の中から、nums[i] + nums[j] + (i - j) の値が最大になるものを見つけることを考えます。例として、入力が nums = [6, 6, 2, 2, 2, 8] の場合、出力は 11 になります。インデックス 0 と 1 の2つの「6」を選ぶと、スコアは 6 + 6 + (0 - 1) = 11 となり、これが最大値となるためです。解法のアプローチこの式は次のように変形できます。nums[i] + nums[j] + (i - j) = (nums[i] + i) + (num
-
Pythonでコインの種類と所持数量から作れる合計金額のパターン数を求める方法
問題の概要コインの額面を格納したリスト coins と、それぞれのコインの所持数量を格納したリスト quantities が与えられます。2つのリストは同じ長さを持ち、i番目のコインの額面は coins[i]、その所持数は quantities[i] です。このとき、これらのコインを1枚以上使用して作り出せる「異なる合計金額」の個数を求めるのが本問題の目的です。具体例入力が以下の場合を考えてみましょう。coins = [1, 2, 5]quantities = [1, 2, 1]この場合、出力は 10 になります。作り出せる合計金額は次の10通りです。[1] → 1[2] → 2[1, 2]