Ceci est une question d'entrevue. Un swap
signifie supprimer tout élément du tableau et l'ajouter à l'arrière du même tableau. Étant donné un tableau d'entiers, recherchez le nombre minimum de swaps
nécessaire pour trier le tableau.
Existe-t-il une solution meilleure que O(n^2)
?
Par exemple:
Tableau d'entrée: [3124].
Le nombre de swaps
: 2 ([3124] -> [1243] -> [1234]).
Cela pourrait fonctionner dans O(nlogn)
même si nous n'assumons pas de tableau de valeurs consécutives.
Si nous le faisons - cela peut être fait dans O(n)
. Une façon de le faire est avec O(n)
espace et O(nlogn)
temps.
Étant donné le tableau A
triez-le (O(nlogn)
) dans un deuxième tableau B
.
maintenant ... (les tableaux sont indexés à partir de 1)
swaps = 0
b = 1
for a = 1 to len(A)
if A[a] == B[b]
b = b + 1
else
swaps = swaps + 1
Le problème se résume à trouver le préfixe le plus long du tableau trié qui apparaît comme une sous-séquence dans le tableau d'entrée. Cela détermine les éléments qui pas doivent être triés. Les éléments restants devront être supprimés un par un, du plus petit au plus grand, et ajoutés à l'arrière.
Dans votre exemple, [3, 1, 2, 4]
, La sous-séquence déjà triée est [1, 2]
. La solution optimale consiste à supprimer les deux éléments restants, 3
Et 4
, Et à les ajouter à l'arrière. La solution optimale est donc deux "swaps".
La recherche de la sous-séquence peut être effectuée en O(n logn)
temps en utilisant O(n)
mémoire supplémentaire. Le pseudo-code suivant le fera (le code est également valide en 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
Si, comme dans votre exemple, le tableau contient une permutation d'entiers de 1
À n
, le problème peut être résolu en O(n)
temps en utilisant O(1)
Mémoire:
l = [1, 2, 3, 5, 4, 6]
s = 1
for item in l:
if item == s:
s += 1
print len(l) - s + 1
Plus généralement, la deuxième méthode peut être utilisée chaque fois que nous connaissons le tableau de sortie a priori et n'avons donc pas besoin de le trouver par tri.
Observation: Si un élément est échangé vers l'arrière, sa position précédente n'a pas d'importance. Aucun élément ne doit être échangé plus d'une fois.
Observation: Le dernier swap (le cas échéant) doit déplacer le plus grand élément.
Observation: Avant le swap, le tableau (hors dernier élément) doit être trié (par les anciens swaps, ou initialement)
algorithme de tri, en supposant que les valeurs sont consécutives: recherchez la sous-séquence triée la plus longue des éléments consécutifs (par valeur) commençant à 1:
3 1 5 2 4
permutez tour à tour tous les éléments supérieurs:
1 5 2 4 3
1 5 2 3 4
1 2 3 4 5
Pour trouver le nombre de swaps dans O (n), trouvez la longueur de la sous-séquence triée la plus longue d'éléments consécutifs commençant à 1:
alors le nombre de swaps = la longueur de l'entrée - sa sous-séquence triée la plus longue.
ne solution alternative (O (n ^ 2)) si l'entrée n'est pas une permutation de 1..n:
Encore une autre solution (O (n log n)), en supposant des éléments uniques:
Si vous ne souhaitez pas copier le tableau d'entrée, triez plutôt par oldPos avant la dernière étape.
c'est une solution O(n) qui fonctionne pour toutes les entrées:
static int minimumSwaps(int[] arr) {
int swap=0;
boolean visited[]=new boolean[arr.length];
for(int i=0;i<arr.length;i++){
int j=i,cycle=0;
while(!visited[j]){
visited[j]=true;
j=arr[j]-1;
cycle++;
}
if(cycle!=0)
swap+=cycle-1;
}
return swap;
}
}
Cela peut être fait dans O (n log n).
Trouvez d'abord l'élément minimum dans le tableau. Maintenant, recherchez l'élément max qui se produit avant cet élément. Appelez ceci max_left
. Vous devez appeler swap()
pour tous les éléments avant l'élément min du tableau.
Maintenant, recherchez la sous-séquence croissante la plus longue à droite de l'élément min, ainsi que la contrainte que vous devez ignorer les éléments dont les valeurs sont supérieures à max_left. Le nombre de swaps requis est size(array) - size(LIS)
.
Par exemple, considérez le tableau,
7 8 9 1 2 5 11 18
L'élément minimum dans le tableau est 1. Nous trouvons donc le max avant l'élément minimum.
7 8 9 | 1 2 5 11 18
max_left = 9
Maintenant, trouvez le LIS à droite de min avec des éléments <9 LIS = 1,2,5
Nombre d'échanges = 8 - 3 = 5
Dans les cas où l'élément max est nul, c'est-à-dire que min est le premier élément, recherchez le LIS du tableau et la réponse requise est size (array) -size (LIS)
Par exemple
2 5 4 3
max_left est nul. LIS est 2 3
Nombre d'échanges = taille (tableau) - taille (LIS) = 4-2 = 2
Voici le code en python pour le nombre minimum de swaps,
def find_cycles(array):
cycles = []
remaining = set(array)
while remaining:
j = i = remaining.pop()
cycle = [i]
while True:
j = array[j]
if j == i:
break
array.append(j)
remaining.remove(j)
cycles.append(cycle)
return cycles
def minimum_swaps(seq):
return sum(len(cycle) - 1 for cycle in find_cycles(seq))
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);
Écrire un programme JavaScript très simple pour trier un tableau et trouver le nombre de swaps:
function findSwaps(){
let arr = [4, 3, 1, 2];
let swap = 0
var n = arr.length
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (arr[i] > arr[j]) {
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j]
swap = swap + 1
}
}
}
console.log(arr);
console.log(swap)
}
def minimumSwaps(arr):
swaps = 0
'''
first sort the given array to determine the correct indexes
of its elements
'''
temp = sorted(arr)
# compare unsorted array with the sorted one
for i in range(len(arr)):
'''
if ith element in the given array is not at the correct index
then swap it with the correct index, since we know the correct
index because of sorting.
'''
if arr[i] != temp[i]:
swaps += 1
a = arr[i]
arr[arr.index(temp[i])] = a
arr[i] = temp[i]
return swaps
Hear est ma solution en c # pour résoudre le nombre minimum de swaps requis pour court-circuiter un tableau A la fois, nous ne pouvons échanger que 2 éléments (à n'importe quelle position d'index).
public class MinimumSwaps2
{
public static void minimumSwapsMain(int[] arr)
{
Dictionary<int, int> dic = new Dictionary<int, int>();
Dictionary<int, int> reverseDIc = new Dictionary<int, int>();
int temp = 0;
int indx = 0;
//find the maximum number from the array
int maxno = FindMaxNo(arr);
if (maxno == arr.Length)
{
for (int i = 1; i <= arr.Length; i++)
{
dic[i] = arr[indx];
reverseDIc.Add(arr[indx], i);
indx++;
}
}
else
{
for (int i = 1; i <= arr.Length; i++)
{
if (arr.Contains(i))
{
dic[i] = arr[indx];
reverseDIc.Add(arr[indx], i);
indx++;
}
}
}
int counter = FindMinSwaps(dic, reverseDIc, maxno);
}
static int FindMaxNo(int[] arr)
{
int maxNO = 0;
for (int i = 0; i < arr.Length; i++)
{
if (maxNO < arr[i])
{
maxNO = arr[i];
}
}
return maxNO;
}
static int FindMinSwaps(Dictionary<int, int> dic, Dictionary<int, int> reverseDIc, int maxno)
{
int counter = 0;
int temp = 0;
for (int i = 1; i <= maxno; i++)
{
if (dic.ContainsKey(i))
{
if (dic[i] != i)
{
counter++;
var myKey1 = reverseDIc[i];
temp = dic[i];
dic[i] = dic[myKey1];
dic[myKey1] = temp;
reverseDIc[temp] = reverseDIc[i];
reverseDIc[i] = i;
}
}
}
return counter;
}
}
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;
}
Ce code renvoie le nombre minimal de swaps requis pour trier un tableau sur place.
Par exemple, A [] = [7,3,4,1] En échangeant 1 et 7, nous obtenons [1,3,4,7]. de même B [] = [1,2,6,4,8,7,9]. Nous échangeons d'abord 6 avec 4, donc, B [] -> [1,2,4,6,8,7,9]. Puis 7 avec 8. Donc -> [1,2,4,6,7,8,9]
L'algorithme s'exécute en O (nombre de paires où la valeur à l'index i <la valeur à l'index i-1) ~ O(N).
@ all, la solution acceptée fournie par @Itay karo et @NPE est totalement fausse car elle ne prend pas en compte la future commande d'éléments échangés ...
Il échoue pour de nombreux cas de test comme:
1 2 5 4
sortie correcte: 4
mais leurs codes donnent la sortie ...
explication: 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: je ne peux pas y commenter à cause de la mauvaise réputation
espace O (1) et O(N) (~ 2 * N) en supposant que l'élément min est 1 et que le tableau contient tous les nombres de 1 à N-1 sans aucune valeur en double. où N est la longueur du tableau.
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 temp = 0, swaps = 0;
for (int i = 0; i < arr.length;) {
if (arr[i] != i + 1){
// System.out.println("Swapping --"+arr[arr[i] - 1] +" AND -- "+arr[i]);
temp = arr[arr[i] - 1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
++swaps;
} else
++i;
// System.out.println("value at position -- "+ i +" is set to -- "+ arr[i]);
}
return swaps;
C'est la réponse la plus optimisée que j'ai trouvée. C'est tellement simple. Vous comprendrez probablement d'un coup d'œil la boucle. Merci à Darryl au rang de hacker.