Pythonで配列からk番目に欠落している正の整数を見つける方法
問題の概要
厳密に増加する正の整数が昇順に並んだ配列 nums と、整数 k が与えられます。このとき、配列に含まれていない正の整数の中から k 番目のものを求めるのが目的です。
例として、nums = [1,2,4,8,12]、k = 6 の場合を考えてみましょう。この配列に存在しない数は [3,5,6,7,9,10,11] であり、その中で 6 番目に当たるのは 10 です。したがって、出力は 10 となります。
解法のアプローチ
この問題は、次の手順で解くことができます。
- 配列
numsの要素をセット(set)に変換し、要素の存在判定を高速化します。 - カウンタ
countを 0、探索対象の数numを 1 で初期化します。 countがk未満である間、以下を繰り返します。numがセットに存在しない場合、countを 1 増やします。countがkと等しくなった時点で、numを答えとして返します。numを 1 増やして次の候補へ進みます。
- ループを抜けた場合は
numをそのまま返します。
Pythonでの実装例
以下のコードは、上記のアルゴリズムを実装したものです。
def solve(nums, k):
nums = set(nums)
count = 0
num = 1
while count < k:
if num not in nums:
count += 1
if count == k:
return num
num += 1
return num
nums = [1,2,4,8,12]
k = 6
print(solve(nums, k))
入力
[1,2,4,8,12], 6
出力
10
計算量について
この解法では、探索する num は最悪でも「配列の最大値 + k」程度までしか進まないため、時間計算量は O(n + k) です。また、セットへの変換に伴い空間計算量は O(n) となります。二分探索を用いれば O(log n) への高速化も可能ですが、コードのシンプルさと分かりやすさを重視するなら、この線形探索のアプローチが適しています。
-
Pythonで1からNまでの範囲の欠落している数字をすべて見つけるプログラム
サイズ n の整数リスト nums があり、リスト内のすべての数値は区間 [1, n] に含まれているとします。このとき、一部の要素は2回出現し、その他は1回だけ出現します。この課題では、[1, n] の範囲のうちリストに存在しない数値(欠落している数字)をすべて見つけ、昇順に並べて返す必要があります。できるだけ線形時間 O(n) で動作する効率的な解法を目指しましょう。 例えば、入力が [4, 4, 2, 2, 6, 6] の場合、出力は [1, 3, 5] となります。 解法のアプローチ この問題は「カウント配列(各数値の出現回数を記録する配列)」を使うことでシンプルに解決できます。手順は
-
Pythonで連続する数値の区間を検出するプログラムの書き方
一意な(重複のない)数値のリスト nums が与えられたとします。このとき、nums 内で連続している数値をひとつの包括的な区間としてまとめ、ソート済みの2次元配列として出力することを目標とします。たとえば、入力が nums = [10, 11, 12, 15, 16, 17, 28, 30] の場合、出力は [[10, 12], [15, 17], [28, 28], [30, 30]] となります。これは、10〜12 と 15〜17 がそれぞれ連続した数値のまとまりである一方、28 と 30 は前後の数値とつながっていないため、単独の区間 [28, 28]、[30, 30] として表現され