-
Pythonで配列の減少・再配置後に取得できる最大要素を求める方法
問題概要 配列 arr が与えられたとします。この配列に対していくつかの操作を行い、次の条件を満たすようにする必要があります。 arr の最初の要素は必ず 1 であること。 隣接する任意の 2 つの要素の絶対差が 1 以内であること。 使用できる操作は次の 2 種類で、それぞれ何度でも実行できます。 arr 内の任意の値を、それより小さい正の整数へ減らす。 arr の要素を任意の順序に並べ替える。 これらの操作を実行して上記の条件を満たしたとき、arr 内に残せる最大の値を求めるのが目的です。 入力例 たとえば arr = [3,3,2,3,2] の場合、出力は 3 になります。これは
-
Pythonで文字列を降順に連続する数値へ分割できるか判定するプログラム
問題の概要 数字のみで構成された文字列 s が与えられたとします。この文字列を2つ以上の空でない部分文字列に分割でき、かつ各部分文字列の数値が降順(非増加順)で並んでいて、隣り合う部分文字列の数値の差がすべて 1 であるかどうかを判定するのが目的です。 例えば、文字列が s = 0080079 の場合、[0080, 079] と分割すると、その数値は [80, 79] となります。値は降順に並んでおり、隣接する値の差も1なので、これは有効な分割です。 入力例 s = 080076 の場合、出力は True になります。なぜなら、[08, 007, 6] と分割すると、数値は [8, 7, 6]
-
Pythonで2つの配列における有効なペアの最大距離を求めるプログラム
非増加(降順)に並べられた2つの配列 nums1 と nums2 が与えられているとします。インデックスのペア (i, j) は、0 <= i < len(nums1)、0 <= j < len(nums2) を満たし、かつ i <= j と nums1[i] <= nums2[j] の両方が成り立つときに「有効なペア」とみなされます。ペアの距離は (j - i) で表され、この問題の目的は、すべての有効なペアの中から最大の距離を見つけることです。有効なペアがひとつも存在しない場合は 0 を返します。 たとえば、nums1 = [60,40,15,10,5]
-
Pythonで部分配列の最大最小積(min-product)を求めるプログラム
問題概要配列 nums が与えられたとき、nums の各空でない部分配列について「最小積(min-product)」を計算し、その中で最大となる値を求めます。答えは非常に大きな数になる可能性があるため、10^9+7 を法とした剰余で返します。ここで、配列の最小積とは「配列内の最小値 × 配列の要素の合計値」として定義されます。例えば、配列が [4,3,6] の場合、最小値は 3 なので、最小積は 3×(4+3+6) = 3×13 = 39 となります。入力が nums = [2,3,4,3] の場合、出力は 30 になります。これは、部分配列 [3,4,3] を選ぶことで結果が最大化され、3×
-
Pythonでn個のキャンディーをk個のバッグに配布する組み合わせの数を求めるプログラム
n個のキャンディーと、それらを入れるためのk個のバッグがあるとします。このとき、各バッグに必ず1個以上のキャンディーが入るように配布する方法が何通りあるかを求める問題です。ここでのポイントは、すべてのキャンディーが互いに異なる(ユニークな)ものであるという点です。そのため、どのキャンディーをどのバッグに入れるかという組み合わせをすべて数え上げる必要があります。 例えば、入力が n = 3、k = 2 の場合、出力は 3 になります。 具体的には、キャンディーは次の3通りの方法で配分できます。 (1, 2), (3) (1), (2, 3) (2), (1, 3) 解法のアプローチ:動的計画法
-
Pythonで配列内の等間隔の要素の合計を求めるプログラム
正の整数からなるサイズ n の配列「nums」と、整数ペア (pi, qi) を要素とする配列「queries」が与えられるとします。各クエリに対する答えは、pi ≤ j < n を満たし、かつ (j − pi) が qi で割り切れるすべての添字 j についての nums[j] の総和です。すべてのクエリの答えを求めてください。ただし、答えが非常に大きな値になる可能性があるため、10^9 + 7 で割った余りを返します。 例として、nums = [2, 3, 4, 5, 6, 7, 8, 9, 10]、queries = [(2, 5), (7, 3), (6, 4)] が入力された場合、出
-
Pythonで1つの座標点を別の座標点へ変換できるかどうかを判定するプログラム
問題の概要 開始点 (sx, sy) と目標点 (tx, ty) が与えられたとき、一連の移動操作によって開始点から目標点へ到達できるかどうかを判定します。ここでいう「移動」とは、ある点 (x, y) を (x, x+y) または (x+y, y) のいずれかに変換する操作のことです。 たとえば、入力が (sx, sy) = (1,1)、(tx, ty) = (4,5) の場合、出力は True になります。(1,1) → (2,1) → (3,1) → (4,1) → (4,5) という移動の連鎖が存在するためです。 解法のアプローチ この問題は、目標点から逆算して開始点に戻れるかを調べる
-
Pythonで2つの文字列の部分列を組み合わせて作れる最長回文の長さを求めるプログラム
問題概要2つの文字列 s と t が与えられたとき、次の手順で新しい文字列を作ることを考えます。s から空でない部分列 sub1 を選びます。t から空でない部分列 sub2 を選びます。sub1 と sub2 を連結して、新しい文字列を作ります。この方法で作成できる回文の中で最も長いものの長さを求めてください。もし一つも回文が作れない場合は 0 を返します。たとえば、s = hillrace、t = cargame という入力の場合、出力は 7 になります。これは、s から race を、t から car を取り出して連結すると racecar という長さ7の回文が作れるためです。解法のアプ
-
Pythonで無向グラフの頂点間に低コストのパスが存在するか判定するプログラム
重み付きの無向グラフが与えられているとします。ここで実装が必要なのは、2つの頂点とコストの上限「limit」を引数として受け取り、その上限より低いコストで両頂点を結ぶパスが存在するかどうかを判定する関数 query() です。条件を満たすパスが存在すれば True を、存在しなければ False を返します。 例として、次のようなグラフを考えてみましょう。 このとき、クエリが (0, 2, 10)、(3, 1, 30)、(4, 3, 30) である場合、出力は次のようになります。 False True True 出力結果の解説 1つ目のクエリ (0, 2, 10) → False: コス
-
Pythonで配列をソート済みにできる最大チャンク数を見つけるプログラム
問題の概要 配列 nums が与えられたとき、この配列をいくつかの区間(パーティション/チャンク)に分割し、それぞれを個別にソートします。その後、すべてを連結した結果が完全にソート済みの配列になるとします。このとき、作成できるパーティションの最大数を求めるのが本記事のテーマです。 例えば、入力が [3,2,4,5,5] の場合、出力は 4 になります。[3,2]、[4][5]、[5] のように4つのパーティションに分割でき、それぞれをソートして連結すると [2,3,4,5,5] という完全に整列した配列が得られるからです。 解法のアプローチ この問題は「貪欲法」で解くことができます。ある区間
-
Pythonで最長のチャンク回文分解の長さを求めるプログラム
この記事では、与えられたテキストに対して「チャンク回文分解」の最大分割数 k を求める問題を、Pythonを使って解く方法を解説します。問題の定義あるテキストが与えられたとき、次の条件をすべて満たすような最大の k を求めます。各 a[i] は空文字列(ブランク)ではない連結した文字列 a[1] + a[2] + ... + a[k] が元のテキストと一致する1 ≤ i ≤ k のすべての i について、a[i] = a[k+1-i] が成り立つ(前から i 番目のチャンクと後ろから i 番目のチャンクが同じ)具体例たとえば、入力が text = antaprezatepzapreanta の
-
Pythonでサイズkの全セグメントのXORをゼロにするための最小変更数を求めるプログラム
配列 nums と整数 k が与えられます。セグメント [left, right](left ≤ right)のXORとは、インデックス left から right まで(両端を含む)のすべての要素をXOR(排他的論理和)した値のことです。 この問題では、サイズ k のすべてのセグメントのXORが 0 となるように配列を書き換えるとき、変更が必要な要素数の最小値を求めます。 たとえば、入力が nums = [3,4,5,2,1,7,3,4,7]、k = 3 の場合、答えは 3 になります。インデックス 2・3・4 の要素を書き換えて [3,4,7,3,4,7,3,4,7] とすれば、どの
-
Pythonで「良い部分配列」の最大スコアを求めるアルゴリズムと実装
問題の概要 整数配列 nums とインデックス k が与えられます。部分配列 (i, j) のスコアは、次のように定義されます。 score(i, j) = min(nums[i..j]) × (j − i + 1) つまり「部分配列内の最小値 × 部分配列の長さ」です。ここで、i ≤ k ≤ j を満たす部分配列を「良い部分配列(good subarray)」と呼びます。この記事の目的は、良い部分配列の中から最大のスコアを見つけることです。 入力例 nums = [2,5,4,8,5,6]、k = 3 の場合を考えてみましょう。最適な部分配列は (1, 5) で、nums[1..5] の最小
-
Pythonで「有効な」配列の最大パワー値を求めるプログラム
問題の概要n個の整数からなる配列 nums があるとします。配列内の各値は、その要素の「パワー(power)」を表しています。この配列は、次の条件を満たすとき「有効(valid)」であるとみなされます。配列の長さが2より大きいこと配列の先頭と末尾の値が等しいこと私たちの課題は、配列から不要な要素を削除して残りの部分がこの条件を満たすようにし、その結果得られる配列のパワー値(全要素の合計)の最大値を返すことです。例として、入力が nums = [3, 4, 5, 3, 4] の場合を考えてみましょう。このとき出力は 16 になります。配列の先頭にある 3 を削除すると、配列は [4, 5, 3,
-
Pythonでn回の操作後に最大スコアを求めるプログラム(ビットマスクDP解説)
問題概要 サイズが 2*n の配列 nums があるとします。この配列に対して、合計 n 回の操作を行います。i 番目の操作(1始まりのインデックス)では、以下の手順を実行します。 配列から2つの要素 x と y を選択する。 i * gcd(x, y) のスコアを獲得する。 選んだ x と y を配列 nums から削除する。 n 回すべての操作を終えたときに得られる最大スコアを求めるのが目標です。 たとえば、入力が nums = [6,2,1,5,4,3] の場合、出力は 14 になります。最適な選び方は次の通りです。 (1 * gcd(1, 5)) + (2 * gcd(2, 4))
-
Pythonで指定範囲内のXORとなるペアを数えるアルゴリズムと実装例
問題の概要配列 nums と2つの整数値 l、r が与えられたとき、「良いペア(nice pair)」の総数を求めることを考えます。ここで良いペアとは、インデックスの組 (i, j) が次の条件を満たすものを指します。0 <= i < j < 配列の長さl <= (nums[i] XOR nums[j]) <= r入力例と出力例たとえば、nums = [4,1,7,2]、l = 2、r = 6 が入力として与えられた場合、出力は 6 になります。これは、以下の6組が良いペアに該当するためです。(0, 1): 4 XOR 1 = 5(1, 2): 1 XOR 7 =
-
Pythonで素敵な約数の個数を最大化するプログラムの解説
問題の概要 整数 pf(素因数の個数)が与えられます。ここで、次の条件を満たす正の整数 n を構成することを考えます。 n の素因数の個数(重複していてもよい)は pf 以下であること n の「素敵な約数(nice divisor)」の個数が最大になること。素敵な約数とは、n のすべての素因数で割り切れる約数のことです。 求めたいのは、そのような n における素敵な約数の個数です。答えが非常に大きくなる可能性があるため、結果は 10^9 + 7 で割った余りとして返します。 例えば、入力が pf = 5 のとき、出力は 6 になります。n = 200 とすると、素因数は [2, 2, 2,
-
Pythonで新鮮なドーナツを受け取れるグループの最大数を求めるプログラム
問題の概要 整数 batchSize(バッチサイズ)と配列 groups が与えられます。groups[i] は、i 番目のグループに groups[i] 人の顧客がいることを意味します。あるドーナツ店では、指定された batchSize 個ずつドーナツを焼いており、「前のバッチのドーナツをすべて提供し終えるまで、次のバッチのドーナツを提供してはならない」というルールがあります。各顧客は必ずドーナツを1個受け取り、あるグループが来店した場合は、そのグループ全員の対応が終わるまで次のグループには対応できません。 グループの全員が新鮮なドーナツを受け取れたとき、そのグループは「幸せ(happy)
-
Pythonで数列の部分列から得られる異なるGCDの個数を求めるプログラム
問題概要 正の整数からなる配列 nums が与えられたとき、nums のすべての空でない部分列についてGCD(最大公約数)を計算し、その結果として現れる「異なるGCDの値」が何種類あるかを求めます。ここで、数列のGCDとは、その数列に含まれるすべての数を余りなく割り切ることができる最大の整数のことです。 入力例と出力例 たとえば、入力が nums = [4, 6, 18] の場合、出力は 4 になります。各部分列のGCDを列挙すると次のようになります。 gcd([4]) = 4 gcd([6]) = 6 gcd([18]) = 18 gcd([4, 6]) = 2 gcd([4, 18])
-
【Python】文字列をソート済みにするまでの最小操作回数を求めるアルゴリズム
問題の概要 文字列 s が与えられます。この文字列に対して、昇順に並んだ「ソート済みの文字列」になるまで、以下の一連の操作を繰り返し適用します。 ステップ1: 1 ≤ i < len(s) を満たし、かつ s[i] < s[i - 1] となる最大のインデックス i を選びます。 ステップ2: i ≤ j < len(s) を満たし、範囲 [i, j] に含まれるすべての k について s[k] < s[i - 1] が成り立つ最大のインデックス j を選びます。 ステップ3: インデックス i - 1 と j の位置にある2つの文字を入れ替えます。 ステップ4: イ