Ecco un punto di partenza: una funzione che controlla se il vincolo può essere soddisfatto da qualche parte all'interno di quell'intervallo ...
def Can_Exist_In_Range (xs, lo, hi) :
return not ((xs [hi] < lo) || (xs [lo] > hi))
Questo sta usando limiti compresi per comodità, che in realtà è una pratica piuttosto cattiva in generale. Se il valore più basso è superiore al limite superiore dell'indice, oppure il valore più alto è inferiore al limite inferiore dell'indice, gli intervalli non possono sovrapporsi (presupponendo che gli indici associati siano in ordine, ovviamente).
Per dividere e conquistare, qualsiasi intervallo che potrebbe contenere un elemento corrispondente dovrebbe essere diviso in sottogruppi non sovrapposti e ogni parte ricorsivamente controllata (a meno che non si ottenga una corrispondenza prima di controllarli tutti). Qualsiasi intervallo che non può contenere un elemento corrispondente, smettere di suddividere e cercare tale intervallo.
Questa non è una ricerca binaria. A meno che non mi manchi qualcosa (in particolare una regola che renda significativi tutti gli elementi della lista come interi unici sarebbe significativa), solo perché il sub-intervallo inferiore viene cercato non significa che puoi immediatamente eliminare il sotto-intervallo superiore, che è il motivo per cui ho commentato che sono curioso di provare che questo può essere fatto in tempo O (log n). In realtà, se permetti numeri non interi, è banale produrre un contro-esempio che ha bisogno del tempo O (n) ...
[0.1, 1.1, 2.1, 3.1, 4.1, ...]
Poiché ogni elemento non è intero, nessun elemento può corrispondere al suo indice. Ma dal momento che ogni elemento è solo leggermente più alto del suo indice, non ci sono intervalli non sovrapposti da eliminare fino ad arrivare al livello di un singolo elemento.
Per spiegare perché, anche con interi (potenzialmente non univoci) potresti aver bisogno di cercare entrambi i sottogruppi, considera ...
* *
Index: 0 1 2 3 4 5, 6, 7
[ 1, 2, 2, 4, 5, 6, 6, 8 ]
Abbiamo una partita in entrambi i tempi. Vogliamo il primo, quindi non c'è bisogno di cercare la seconda metà, ma non possiamo sapere che fino a dopo abbiamo cercato il primo semestre. Nessuno dei due subrange può essere eliminato fino a quando la ricerca non viene completata. Dopo tutto ...
*
Index: 0 1 2 3 4 5, 6, 7
[ 1, 2, 3, 4, 5, 6, 6, 8 ]
... quando facciamo lo split, non ne sappiamo abbastanza per dimostrare che il primo subrange contiene una corrispondenza - potrebbe non esserlo, nel qual caso l'unica corrispondenza che abbiamo è quella del secondo subrange.