-
Pythonで全ての点を接続するための最小コストを求めるプログラム
問題の概要(x, y) の形式で表される複数の点が格納された配列 points があるとします。2つの点 (xi, yi) と (xj, yj) を接続するコストは、それらの間のマンハッタン距離として定義されます。マンハッタン距離は次の式で計算できます。|xi − xj| + |yi − yj|この問題では、すべての点を接続するために必要な最小のコストを求める必要があります。入力例points = [(0,0), (3,3), (2,10), (6,3), (8,0)]この場合、出力は 22 になります。これは、各辺の距離がそれぞれ 6 + 5 + 3 + 8 = 22 となるように点同士を接
-
Pythonで順列の中からリクエスト合計が最大になる並べ方を見つける方法
問題の概要 配列 nums と、リクエストを表す配列 requests があります。requests[i] = [start_i, end_i] は、i 番目のリクエストが nums[start_i] + nums[start_i+1] + ... + nums[end_i] の総和を求めることを意味します。ここで、nums のすべての順列の中から、全リクエストの合計が最大になる並べ方を見つけます。答えは非常に大きな数になる可能性があるため、109+7 で割った余りを返します。 たとえば、入力が nums = [10,20,30,40,50]、requests = [[1,3],[0,1]]
-
【Python】合計がpで割り切れるようにする最小の部分配列を求める方法
問題の概要配列 nums と整数 p が与えられたとき、「残りの要素の合計が p で割り切れる」状態を作るために、最小の部分配列(ただし配列全体は削除しない)を取り除くことを考えます。求めたいのは削除すべき最小の部分配列の長さであり、そのような部分配列が存在しない場合は -1 を返します。例えば、nums = [8,2,6,5,3]、p = 7 の場合を考えてみましょう。このとき出力は 1 になります。なぜなら、末尾の要素「3」を削除すれば残りの合計は 21 となり、21 は 7 で割り切れるからです。解法のアイデア:累積和と剰余の活用この問題は、累積和(プレフィックスサム)の剰余を利用するこ
-
Pythonで文字列を一意な部分文字列に分割したときの最大数を求める方法
文字列 s が与えられたとき、その文字列を分割して得られる一意な部分文字列の最大数を見つける必要があります。文字列 s は、空でない部分文字列のリストに自由に分割でき、それらを連結すると元の文字列と一致しなければなりません。ただし、分割後のすべての部分文字列は互いに重複してはならず、すべて異なるものである必要があります。たとえば、入力が s = pqpqrrr の場合、出力は 5 になります。これは [p, q, pq, r, rr] のように分割できるためです。一方、[p, q, p, q, r, rr] のような分割は無効です。この場合、p と q が複数回現れているためです。解決アプロー
-
Pythonで行列の経路における最大の非負の積を求めるプログラム
問題概要 m × n の行列が与えられます。スタート地点は左上のセル (0, 0) で、各ステップでは右または下にのみ移動できます。左上のセル (0, 0) から右下のセル (m-1, n-1) に至るすべての経路の中から、通過するセルの値の積が最大となる「非負の積」を持つ経路を見つけます。答えが非常に大きくなる場合は、最大の非負の積を 10^9+7 で割った余りを返します。 例 たとえば、入力が次の行列だったとします。 2-422-424-82 このとき出力は 256 になります。下の表で色を付けた経路を選んだ場合、積は次のように計算されます。 2-422-424-82 積は [2 × 2
-
Pythonで行と列の合計を満たす有効な行列を見つけるプログラム
問題の概要2つの配列 rowSum と colSum があり、それぞれ非負の整数が格納されているとします。rowSum[i] は2次元行列の i 行目の要素の合計を、colSum[j] は j 列目の要素の合計を表します。このとき、与えられた rowSum と colSum の条件をすべて満たすような、非負の値のみで構成されたサイズ(rowSumの長さ × colSumの長さ)の行列を1つ見つける必要があります。例として、入力が rowSum = [13,14,12]、colSum = [9,13,17] の場合、出力は次のようになります。9400950012この行列では、各行の合計が 13・
-
Pythonで都市ネットワークの最大ネットワークランクを求めるプログラム
n個の都市があり、いくつかの道路によって相互に接続されているとします。roads[i] = [u, v] は、都市uと都市vの間に双方向の道路が1本存在することを表します。 ここで「ネットワークランク」とは、ある2つの異なる都市のペアについて、そのどちらかの都市に直接接続されている道路の総数を指します。ただし、2つの都市の両方に直接つながっている道路は、重複を避けるために1本としてのみカウントします。そして「最大ネットワークランク」とは、取り得るすべての都市ペアの中で最も大きなネットワークランクの値のことです。与えられた道路情報をもとに、ネットワーク全体の最大ネットワークランクを求めましょう。
-
Pythonで重ならないk本の線分の組み合わせ数を求めるプログラム
問題の概要 数直線上にn個の点が並んでいるとします。i番目の点(0からn-1まで)は、位置x = iに配置されています。このとき、ちょうどk本の異なる線分を、互いに重ならないように引く方法が何通りあるかを求めるのがこの問題です。ただし、各線分は2つ以上の点をカバーする必要があります。 主な条件を整理すると、次のようになります。 各線分の両端点は整数座標でなければならない k本の線分は、与えられたn個の点をすべてカバーする必要はない 線分同士は端点を共有してもよい(内部が重ならなければよい) 答えが大きくなりすぎる場合は、10^9 + 7で割った余りを返す 入力例と出力例 たとえば、n =
-
【Python】加算と回転操作から辞書順最小の文字列を求めるプログラム
問題の概要 数字のみで構成された文字列 s と、2つの整数 a・b が与えられます。文字列 s に対しては、次の2つの操作を任意の回数・任意の順序で適用できます。 加算操作:奇数番目(インデックスは0始まり)のすべての桁に a を加えます。9にさらに加算した場合は0に戻る(循環する)ものとします。 回転操作:文字列 s を右方向に b 桁だけ回転します。 目的は、これらの操作を何度でも組み合わせて得られる文字列の中から、辞書順で最小の文字列を見つけることです。 入力例と出力例 たとえば、s = 5323、a = 9、b = 2 が与えられた場合、出力は 2050 になります。この結果に至
-
Pythonで競合のない最高スコアのチームを見つけるプログラム
バスケットボールの試合を想定し、2つのリスト「scores」と「ages」が与えられているとします。scores[i] と ages[i] は、それぞれ i 番目のプレイヤーのスコアと年齢を表します。目的は、合計スコアが最も高いチームを選出することです。チームのスコアは、所属する全プレイヤーのスコアの総和として定義されます。 ただし、試合では「競合」が許されません。競合とは、より若いプレイヤーが、より年上のプレイヤーよりも厳密に高いスコアを持っている状態を指します。 例えば、入力が scores = [5,7,9,14,19]、ages = [5,6,7,8,9] の場合、出力は 54 になり
-
Pythonで最小限の労力でパスを見つけるプログラム
問題の概要m × n の2次元行列 heights が与えられます。heights[i][j] はセル (i, j) の高さを表します。現在セル (0, 0) にいて、右下のセル (m-1, n-1) まで移動したいとします。移動は上下左右の4方向が可能で、「労力」が最小になるような経路を見つけることが目的です。ここでいう「労力」とは、経路上で隣り合う2つのセル間の高さの絶対差のうち、最大値のことです。つまり、目的地に到達するために必要な最小の労力を求める必要があります。入力例234495646この場合の出力は 1 になります。経路 [2, 3, 4, 5, 6] を通ると、隣接セル間の高さの
-
【Python】2つの文字列で1文字だけ異なる部分文字列のペアを数える方法
問題概要2つの文字列 s と t が与えられます。s から空でない部分文字列を1つ選び、その中のちょうど1文字を別の文字に置き換えたとき、結果が t の部分文字列と一致するような組み合わせの総数を求めるのが目的です。入力例s = sts、t = tsts出力例6この場合、s と t から選んだ部分文字列のペアのうち、ちょうど1文字だけ異なるものは次の6組です。(s, t):s[0] と t[0](s, t):s[0] と t[2](t, s):s[1] と t[1](t, s):s[1] と t[3](s, t):s[2] と t[0](s, t):s[2] と t[2]長さ2以上の部分文字列
-
Pythonで辞書順にソートされた母音文字列の数を求めるプログラム
数 n が与えられたとき、母音(a、e、i、o、u)だけから構成され、かつ辞書順(アルファベット順)にソートされている長さ n の文字列が全部で何通りあるかを求めます。ここで「文字列 s が辞書順にソートされている」とは、すべてのインデックス i について、s[i] が s[i+1] と同じ文字であるか、アルファベット上でより前に位置することを意味します。 たとえば入力が n = 2 のとき、出力は 15 になります。これは ["aa", "ae", "ai", "ao", "au", &qu
-
Pythonで各文字の出現頻度を一意にするために必要な最小削除数を求めるプログラム
問題の概要文字列 s が与えられます。s に含まれる異なる2つの文字が同じ出現頻度を持たないとき、s は「良い文字列(good string)」であると定義します。ここでの課題は、s を良い文字列に変換するために削除が必要な文字の最小数を求めることです。例えば、入力が s = ssstttuu の場合、答えは 2 になります。まず t を1つ削除すると、s が3個、t が2個、u が2個となります。このままでは t と u の頻度が重複しているため、さらに t または u のどちらかを1つ削除すると、すべての頻度が一意になり、良い文字列が完成します。解決のための手順この問題を解くには、以下の手
-
【Python】配列の両端から要素を削除してXをちょうど0にする最小操作回数を求めるアルゴリズム
問題の概要 数値の配列 nums と値 x が与えられます。1回の操作では、配列の左端または右端の要素を1つ削除し、その値を x から差し引きます。x をちょうど 0 にするために必要な最小の操作回数を求めてください。どうしても達成できない場合は -1 を返します。 入力例と動作の流れ たとえば、nums = [4,2,9,1,4,2,3]、x = 9 が入力された場合、出力は 3 になります。具体的な手順は次のとおりです。 まず左端の要素 4 を削除 → 配列は [2,9,1,4,2,3] となり、x は 5 になります。 次に右端の要素 3 を削除 → 配列は [2,9,1,4,2] と
-
Pythonで指定した数値を持つ辞書順最小の文字列を求めるプログラム
問題の概要 2つの整数 n と k が与えられます。求めるのは、長さが n で、数値(合計値)がちょうど k に等しい、辞書順で最小の文字列です。 ここでいう「数値」とは、小文字アルファベットをアルファベット順の位置(1始まり)に対応させた値のことです。「a」は1、「b」は2、「c」は3……というように対応し、「z」は26になります。また、小文字のみで構成される文字列の数値は、その文字列を構成する各文字の数値の総和として定義されます。 たとえば、入力が n = 4、k = 16 の場合、出力は「aaam」になります。1 + 1 + 1 + 13 = 16 となり、条件を満たす長さ4の文字列の中
-
Pythonで公正な配列を作れる削除インデックスの数を求めるプログラム
問題の概要 配列 nums が与えられたとします。私たちはちょうど1つのインデックスを選び、その位置にある要素を削除できます(削除後は残りの要素が前に詰まり、インデックスが変化することに注意してください)。 ここで、偶数番目(インデックス0, 2, 4, …)の値の合計と奇数番目(インデックス1, 3, 5, …)の値の合計が等しいとき、その配列を「公正(fair)」であると呼びます。求めたいのは、1つの要素を削除した結果として配列が公正になるような、インデックスの選び方の総数です。 入力例と考え方 たとえば入力が nums = [5,3,7,2] の場合、出力は 1 になります。各インデッ
-
Pythonでフードパケットを受け取れない人数を求めるプログラム
問題の概要 ある会議には、2種類の人々がいるとします。1つ目はベジタリアン(菜食)の昼食を希望する人々、もう1つは非菜食の昼食を希望する人々です。しかし、用意されているパケットの数は限られており、もし菜食希望者が非菜食のパケットを受け取った場合(またはその逆の場合)、その人はそのパケットを受け取らず、自分の希望するパケットが手に入るまで待ちます。 そこで、2種類のパケットと人々を、菜食を「0」、非菜食を「1」として表します。入力として、0と1で表されたn個のフードパケットを含む配列と、m人の行列(順番待ち)の希望を0と1で表した配列の2つが与えられます。もし誰かが自分の希望するパケットを受け取
-
Pythonで連結リストをマージするプログラムの実装手順を解説
長さ m の連結リスト L1 と、長さ n の連結リスト L2 があるとします。さらに、2つの位置 a と b も与えられています。この問題では、L1 の a 番目のノードから b 番目のノードまでを削除し、その部分に L2 を挿入してマージします。 例えば、入力が L1 = [1,5,6,7,1,6,3,9,12]、L2 = [5,7,1,6]、a = 3、b = 6 の場合、出力は [1, 5, 6, 5, 7, 1, 6, 9, 12] になります。これは、L1 のインデックス 3〜6 に相当する「7, 1, 6, 3」が取り除かれ、代わりに L2 の「5, 7, 1, 6」が挿入され
-
Pythonで配列を「2倍ペア」に並べ替えられるか判定するプログラム
偶数の長さを持つ整数配列 nums が与えられたとします。この配列を並べ替えることで、すべてのインデックス i(0 ≤ i < len(nums)/2)に対して nums[2*i + 1] = 2*nums[2*i] という条件が成り立つようにできるかどうかを判定するのが、この記事のテーマです。 例えば、nums = [4, -2, 2, -4] の場合、[-2, -4, 2, 4] の順に並べ替えると各ペアが「前の要素のちょうど2倍」という関係を満たすため、答えは True になります。 解法の考え方 この問題は、各要素とその2倍の値をきちんとペアにできるかを確認することで解けます。ア