これは面接の質問です。swap
配列から要素を削除し、同じ配列の後ろに追加することを意味します。整数の配列が与えられたら、swaps
配列をソートするために必要な最小数を見つけます。
より良い解決策はありO(n^2)
ますか?
例えば:
入力配列:[3124]。
数swaps
:2([3124]-> [1243]-> [1234])。
これは面接の質問です。swap
配列から要素を削除し、同じ配列の後ろに追加することを意味します。整数の配列が与えられたら、swaps
配列をソートするために必要な最小数を見つけます。
より良い解決策はありO(n^2)
ますか?
例えば:
入力配列:[3124]。
数swaps
:2([3124]-> [1243]-> [1234])。
問題は、入力配列にサブシーケンスとして表示される、ソートされた配列の最長のプレフィックスを見つけることに要約されます。これにより、並べ替える必要のない要素が決まります。残りの要素は、小さいものから大きいものへと1つずつ削除し、後ろに追加する必要があります。
あなたの例で[3, 1, 2, 4]
は、すでにソートされているサブシーケンスは[1, 2]
です。最適な解決策は、残りの2つの要素とを削除し、3
それら4
を後ろに追加することです。したがって、最適なソリューションは2つの「スワップ」です。
サブシーケンスの検索は、追加のメモリO(n logn)
を使用して時間内に実行できます。O(n)
次の擬似コードがそれを行います(コードはたまたま有効なPythonでもあります):
l = [1, 2, 4, 3, 99, 98, 7]
s = sorted(l)
si = 0
for item in l:
if item == s[si]:
si += 1
print len(l) - si
あなたの例のように、配列にから1
までの整数の順列が含まれている場合、メモリを使用して問題を時間n
内に解決できます。O(n)
O(1)
l = [1, 2, 3, 5, 4, 6]
s = 1
for item in l:
if item == s:
s += 1
print len(l) - s + 1
より一般的には、2番目の方法は、出力配列が事前にわかっている場合はいつでも使用できるため、並べ替えによって見つける必要はありません。
これはO(nlogn)
、連続した値の配列を想定していない場合でも機能する可能性があります。
もしそうなら - それはで行うことができますO(n)
。それを行う1つの方法は、O(n)
空間とO(nlogn)
時間です。
指定された配列を 2 番目の配列にA
並べ替えます ( O(nlogn)
) B
。
今... (配列は 1 からインデックス付けされます)
swaps = 0
b = 1
for a = 1 to len(A)
if A[a] == B[b]
b = b + 1
else
swaps = swaps + 1
観察: 要素が後ろにスワップされた場合、その前の位置は問題になりません。要素を複数回交換する必要はありません。
観察: 最後のスワップ (ある場合) は、最大の要素を移動する必要があります。
観察: スワップの前に、配列 (最後の要素を除く) をソートする必要があります (以前のスワップによって、または最初に)
値が連続的であると仮定した並べ替えアルゴリズム: 1 から始まる連続した (値による) 要素の並べ替えられた最長の部分列を見つけます。
3 1 5 2 4
上位のすべての要素を順番に入れ替えます。
1 5 2 4 3
1 5 2 3 4
1 2 3 4 5
O(n)でスワップの数を見つけるには、1 から始まる連続した要素の最長の並べ替えられたサブシーケンスの長さを見つけます。
次に、スワップの数 = 入力の長さ - その最長のソートされたサブシーケンス。
入力が 1..n の順列でない場合の代替ソリューション( O(n^2) ):
一意の要素を想定したさらに別のソリューション( O(n log n) ):
入力配列をコピーしたくない場合は、代わりに最後のステップの前に oldPos で並べ替えます。
O(1) スペースと O(N) (~ 2*N) ソリューションは、最小要素が 1 で、配列に 1 から N-1 までのすべての数値が重複値なしで含まれていると仮定します。ここで、N は配列の長さです。
int minimumSwaps(int[] a) {
int swaps = 0;
int i = 0;
while(i < a.length) {
int position = a[i] - 1;
if(position != i) {
int temp = a[position];
a[position] = a[i];
a[i] = temp;
swaps++;
} else {
i++;
}
}
return swaps;
}
int numSwaps(int arr[], int length) {
bool sorted = false;
int swaps = 0;
while(!sorted) {
int inversions = 0;
int t1pos,t2pos,t3pos,t4pos = 0;
for (int i = 1;i < length; ++i)
{
if(arr[i] < arr[i-1]){
if(inversions){
tie(t3pos,t4pos) = make_tuple(i-1, i);
}
else tie(t1pos, t2pos) = make_tuple(i-1, i);
inversions++;
}
if(inversions == 2)
break;
}
if(!inversions){
sorted = true;
}
else if(inversions == 1) {
swaps++;
int temp = arr[t2pos];
arr[t2pos] = arr[t1pos];
arr[t1pos] = temp;
}
else{
swaps++;
if(arr[t4pos] < arr[t2pos]){
int temp = arr[t1pos];
arr[t1pos] = arr[t4pos];
arr[t4pos] = temp;
}
else{
int temp = arr[t2pos];
arr[t2pos] = arr[t1pos];
arr[t1pos] = temp;
}
}
}
return swaps;
}
このコードは、配列をインプレースでソートするために必要なスワップの最小数を返します。
たとえば、A[] = [7,3,4,1] 1 と 7 を交換すると、[1,3,4,7] が得られます。同様に、B[] = [1,2,6,4,8,7,9]. 最初に 6 を 4 と交換するので、B[] -> [1,2,4,6,8,7,9] になります。次に 7 と 8 です。つまり -> [1,2,4,6,7,8,9]
アルゴリズムは O(インデックス i の値 < インデックス i-1 の値のペアの数) ~ O(N) で実行されます。
for(int count = 1; count<=length; count++)
{
tempSwap=0; //it will count swaps per iteration
for(int i=0; i<length-1; i++)
if(a[i]>a[i+1])
{
swap(a[i],a[i+1]);
tempSwap++;
}
if(tempSwap!=0) //check if array is already sorted!
swap += tempSwap;
else
break;
}
System.out.println(swaps);
@all 、@Itay karo および @NPE によって提供される受け入れられたソリューションは、スワップされた要素の将来の順序を考慮していないため、完全に間違っています...
次のような多くのテストケースで失敗します。
3 1 2 5 4
正しい出力: 4
しかし、それらのコードは出力を3 ...
説明: 3 1 2 5 4--->1 2 5 4 3--->1 2 4 3 5--->1 2 3 5 4--->1 2 3 4 5
PS:評判が悪いのでコメントできません