Algoritmo per ordinare le coppie di numeri


14

Ho già fatto questa domanda su StackOverflow , ma forse è più adatto a questo sito.

Il problema è:

Ho N coppie di numeri interi senza segno. Devo ordinarli. Il vettore finale delle coppie deve essere ordinato in modo non crescente in base al primo numero in ciascuna coppia e in modo non crescente in base al secondo in ciascuna coppia. Ogni coppia può avere il primo e il secondo elemento scambiati in qualsiasi momento. A volte non c'è soluzione, quindi devo lanciare un'eccezione.

Esempio:

in pairs:
1 5
7 1
3 8
5 6

out pairs:
1 7     <-- swapped
1 5     
6 5     <-- swapped
8 3     <-- swapped

^^ Senza scambiare coppie è impossibile costruire la soluzione. Quindi scambiamo coppie (7, 1), (3, 8) e (5, 6) e costruiamo il risultato. o

in pairs:
1 5
6 9

out:
not possible

Grazie

modificare:

Tom Sirgedas su SO ha proposto la soluzione migliore . È davvero facile da implementare e funziona in O (log (n) * n). Grazie a tutti per le risposte e l'interesse. Mi è davvero piaciuta l'analisi mjqxxxx.


6
Problema interessante. Senza lo scambio è semplice, ma con lo scambio non è chiaro che esiste una soluzione unica.
Dave Clarke,

2
La soluzione unica non esiste sempre per certo. Vale a dire (1, 10), (5, 6). Entrambi (1, 10), (5, 6) e (1, 10), (6, 5) sono corretti.
Klark

4
La prossima volta includi un link. stackoverflow.com/questions/5323941/…
Tsuyoshi Ito

2
Un mio amico l'ha ricevuto come domanda per un colloquio di prova. Quindi immagino sia solo per curiosità :)
Klark

3
(1) Klark, grazie per la risposta. (2) Non penso che questa domanda sia una domanda a livello di ricerca, ma immagino che sia la portata che dovrebbe essere cambiata. Ho iniziato una discussione su meta .
Tsuyoshi Ito,

Risposte:


8

Supponiamo che due coppie e p 2 = ( a 2 , b 2 ) non siano compatibili con lo swap se possono essere inserite in entrambi gli ordini nell'elenco ordinato senza scambiare nessuno dei due. Questo è vero se ( a 1a 2b 1b 2 ) o ( a 2a 1b 2bp1=(un'1,B1)p2=(un'2,B2)(un'1un'2B1B2) . Si noti che p 1 e p 2 sono compatibili senza scambio se e solo se sonocompatibili con due scambi(poiché l'ordine parziale definito soddisfa p 1p 2p 2p 1 , dove indica l'operazione di scambio) . Infine, p 1 e p 2 sonocompatibili con uno scambiose possono essere inseriti in entrambi gli ordini nell'elenco ordinato con uno di essi esattamente scambiato. Questo è vero se p 1 e(un'2un'1B2B1)p1p2p1p2p2*p1**p1p2p1* sono compatibili senza scambio. Nei restanti casi, p 1 e p 2 sono semplicemente incompatibili: non possono soddisfare le condizioni dell'ordine indipendentemente dal loro stato di scambio.p2p1p2

Il problema ora può essere risolto come segue. Prova ogni coppia di coppie. Se una coppia è incompatibile, non esiste una soluzione e possiamo generare un'eccezione. In caso contrario, considerare il grafico con nodi corrispondenti alle coppie originali e bordi tra quelle coppie di nodi che non sono compatibili con uno scambio. Ciascuna di tali coppie di nodi deve avere lo stesso stato di scambio in qualsiasi elenco correttamente ordinato, e quindi tutti i nodi in ciascun componente collegato del grafico devono avere lo stesso stato di scambio. Dobbiamo determinare se questi stati di scambio a livello di componente possono essere assegnati in modo coerente. Testa tutte le coppie di nodi all'interno di ciascun componente collegato. Se una coppia non è compatibile no-swap, non esiste una soluzione e possiamo generare un'eccezione. Ora testare tutte le coppie di componenti collegati (cioè, per i componenti C1e , testare tutte le coppie di nodi p 1C 1 e p 2C 2 ). Sappiamo che ogni coppia di componenti è almeno compatibile con uno scambio, ma alcune coppie potrebbero anche non essere compatibili con lo scambio (poiché ogni coppia di nodi non collegati da un bordo è almeno compatibile con uno scambio e potrebbe anche non essere compatibile con swap). Considera un grafico ridotto con nodi corrispondenti ai componenti collegati e uno spigolo tra due nodi se i componenti corrispondenti non sono compatibili senza scambio. C'è una soluzione al problema originale se e solo se questo grafico è a 2 colori. Se non ce n'è 2C2p1C1p2C222-colore, non esiste soluzione e possiamo fare un'eccezione. Se ce n'è uno, scambia tutti i nodi in tutti i componenti di un singolo colore. Ora siamo garantiti che due nodi qualsiasi non sono compatibili con lo scambio e quindi possiamo ordinare correttamente l'elenco di coppie usando l'ordine parziale definito.

Ogni fase dell'algoritmo, e quindi l'intero algoritmo, può essere eseguita in tempo .O(N2)


AGGIORNAMENTO: Una costruzione molto più elegante è la seguente. Se una coppia di coppie non è compatibile no-swap, collega i nodi corrispondenti con un bordo (forzandoli ad avere colori diversi in qualsiasi 2 colori). Se una coppia di coppie non è compatibile con uno scambio, collegare i nodi corrispondenti con una catena di lunghezza 2 (costringendoli ad avere lo stesso colore in qualsiasi 2 colori). C'è una soluzione se e solo se il grafico risultante è bicolore. Per costruire una soluzione da una colorazione blu-rossa del grafico, scambia solo quelle coppie i cui nodi corrispondenti sono blu, quindi ordina l'elenco risultante.


1
Grazie mille per la tua risposta. Mi è davvero piaciuto leggerlo. Controlla la risposta proposta su SO. Anche se non si basa sulla teoria dei grafi, il che significa che è meno interessante della tua soluzione elegante :), è più veloce. Grazie per il tuo tempo.
Klark

3

Sia X (a, b) denota la variabile binaria che indica se la coppia (a, b) deve essere scambiata. Considera qualsiasi coppia di coppie distinte (a, b) e (c, d) e scrivi un vincolo binario sulle variabili X (a, b) e X (c, d) che è soddisfatto se e solo se le due coppie sono in l'ordine corretto dopo aver eseguito gli swap indicati da X (a, b) e X (c, d), rispettivamente. La congiunzione di tutti questi vincoli binari è una formula 2-SAT in n variabili e clausole O (n ^ 2) che è soddisfacente se e solo se il problema originale ha una soluzione. Questo può essere verificato nel tempo O (n ^ 2).


Per quanto riguarda la soluzione originale, basta notare che tutti i vincoli sono nella forma X (a, b) = X (c, d) o X (a, b)! = X (c, d) (oppure X (a, b) = costante), quindi funziona un semplice algoritmo "unisci e verifica la bipartiticità":

Inizia con ogni X come rappresentante per l'insieme contenente solo se stesso; quindi per ogni coppia (X, Y) tale che X = Y sia un vincolo, unisci i componenti a cui X e Y appartengono; e infine controlla che il grafico contratto, in cui ogni componente è un vertice e un bordo si unisce ai componenti che contengono X e Y se la relazione X! = Y deve contenere, è bipartito.


1
X(un',B)=X(c,d)

Così? La relazione di equivalenza qui è la chiusura transitiva della relazione (a, b) R (c, d) iff a <c e b> d o viceversa. Forse non ero completamente esplicito, ma questo dovrebbe essere ovvio dalla mia risposta.
david

1
un'<cB>dX(un',B)X(c,d)(1,10)(2,5)(3,7)

1
XYX¬Y

1
Stai scherzando? Prima di tutto, qualsiasi relazione tra solo due variabili può essere espressa come una formula 2-SAT. Ad esempio, X = Y è uguale a (X implica Y) e (non X implica non Y). D'altra parte, se tutti i vincoli sono effettivamente della forma X = Y o X = non Y, non è necessario eseguire l'algoritmo 2SAT: l'algoritmo "unisci e verifica la bipartiticità" più semplice che ho descritto in precedenza funziona.
david
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.