重複を含む可能性のある配列が与えられた場合、それがシーケンスであるかどうかをどのように確認できますか?
例えば。{7, 3, 5, 4, 6, 2}
シーケンスです2, 3, 4, 5, 6, 7
並べ替えは明らかな解決策です。O(n) 時間と O(1) 空間でこれを行うにはどうすればよいでしょうか?
重複を含む可能性のある配列が与えられた場合、それがシーケンスであるかどうかをどのように確認できますか?
例えば。{7, 3, 5, 4, 6, 2}
シーケンスです2, 3, 4, 5, 6, 7
並べ替えは明らかな解決策です。O(n) 時間と O(1) 空間でこれを行うにはどうすればよいでしょうか?
1,2,3,3,4,1
が有効なソートされていないシーケンスで2,4,6,8
あり、(ステップ 2 の) 有効なシーケンスでもあると仮定しますが、そう1,3,5,9
ではなく (7 がありません)、入力配列を上書きできると仮定します。
a_n - min
max - min > (count + 1) * step
)、これはシーケンスではありません。さもないと、v_0
(v_0 - min) / step + start
) をi
start
の場合、重複しています。後ろに移動し、エンドポインターをデクリメントしますend
、シーケンス内に欠落している要素があります。配列がシーケンスではないと主張します。min
参照をインクリメントしますv_0
、それを配列の最後にスワップし、終了ポインターをデクリメントします。複製です。v_0
ます。インプレース整数ソートは O(n) です。各ステップで、次のいずれかです。
並べ替えの最後に、各要素は重複ブロック内で重複しているか、並べ替えられたブロック内の正しい位置にあります。
手順 3 は省略できることに注意してください。#4は、これがシーケンスではないと正しく判断しますが、遅くなります。
ステップが 1 でなければならない場合、このアルゴリズムはいくらか単純化できます (リビジョン #1 を参照)。
このアルゴリズム (Python) は元の配列を破棄しますが、それ以外の場合は O(n) 時間と O(1) 余分なスペースを満たします。
# INPUT: An array 'arr' of N integers.
# OUTPUT: If the array consists exactly of the integers
# S, S+1, ..., S+N-1, for some S, in any order,
# then modifies 'arr' into a sorted array and returns it.
# Otherwise, returns False, and 'arr' may have been modified.
def sort_sequence (arr):
the_min = min(arr)
the_max = max(arr)
if the_max - the_min != len(arr) - 1:
return False
for i in range(len(arr)):
arr[i] -= the_min
for i in range(len(arr)):
while arr[i] != i:
j = arr[i]
t = arr[j]
if t == j:
return False
arr[j] = j
arr[i] = t
for i in range(len(arr)):
arr[i] += the_min
return arr
まだ機能することを正式に証明していません。
これはなぜ O(n) なのですか? 最後の二重ループでは、要素が最初に正しい場所に配置された後、もう一度だけアクセスできます - 正しい場所にあると見なされる別の内部ループの開始時、または見つかった場所のいずれかです。重複する要素 (if t == h
パーツ) の邪魔にならないようにします。
試してみましょう:
public bool IsSequence(int[] values)
{
var min = values[0];
var max = values[0];
foreach (var value in values)
{
min = min > value ? value : min;
max = max > value ? max : value;
}
if ((max - min + 1) != values.Length)
return false;
var testingArray = new int?[values.Length];
foreach (var value in values)
{
var index = value - min;
if (testingArray[index].HasValue)
return false;
else
testingArray[index] = value;
}
return true;
}