Binärer Suchalgorithmus - wo liegt der Fehler?

4 Antworten

    while(left <= right) {

Du hörst erst auf, wenn das Intervall leer ist. Ich hätte erwartet, dass die Suche zu Ende ist, wenn zwei benachbarte Werte l, r mit l≤value≤r gefunden wurden.

        int middle = left + (right - left) / 2;
        int difference = Math.abs(value - sortedData[middle]);

        if(difference < currentSmallest) {

Wozu diese Abfrage? In einem sortierten Array kann doch difference>currentSmallest gar nicht passieren.

            currentSmallest = difference;
            nearestindex = middle;

Wieso middle? Könnte bei middle+1 oder middle-1 nicht ein besserer Wert stehen? Ich bin mir nicht sicher, ob das im nächsten Durchlauf (falls es noch einen gibt) repariert wird.

  if(Math.abs(value - nearestindex) > Math.abs(value - middle)) {

Das ist gruselig. Bei hinreichend großem value testest Du nearestindex<middle (was auch immer das bezwecken soll). Wenn value kleiner als die betrachteten Indizes ist, testest Du nearestindex>middle. Und bei einem value dazwischen passieren seltsame Dinge.

Besonders schräg wird diese Sache dadurch, dass nearestindex=middle in nächsten Durchlauf garantiert außerhalb des Intervalls liegt, weil Du ja entweder vor oder hinter middle weitersuchst.

Ich denke, Du hast Dir mit dem Tracken der Differenz einen Knoten ins Hirn gemacht. Implementiere einfach eine Intervallschachtelung bis runter zur Intervalllänge ≤2, und gib dann die bessere Grenze zurück.

Vergiss nicht zu prüfen, ob die Sonderfälle value<sortedData[0] und value>sortedData[len-1] sauber durchlaufen. Falls nicht, musst Du das getrennt abbacken.

Ich verstehe nicht, warum Du nciht einfach bei erfolgloser Suche let oder right zurückgibst.

. Welcher der beiden Indices ist dabei egal, solange der zurückgegebene Index im Array liegt.

tumas 
Beitragsersteller
 28.04.2024, 23:10

Bei einer erfolglosen Suche left oder right zurückzugeben, wäre ungenau, da diese Indizes am Ende der Suche oft auf Positionen zeigen, die nicht den nächstgelegenen Wert zum gesuchten Wert enthalten.

KarlRanseierIII  28.04.2024, 23:44
@tumas
die nicht den nächstgelegenen Wert zum gesuchten Wert enthalten.

Das wird wo genau gefordert?

tumas 
Beitragsersteller
 29.04.2024, 14:40
@KarlRanseierIII

> Task :BinSea.main()

added step to index 2

added step to index 0

added step to index 1

1
korrekter Output.

KarlRanseierIII  29.04.2024, 20:39
@tumas

Ah, hatte vergessen, daß Du erst bei left>right abbrichst und nochmal die Position wechselst.

Dann gibt es im Endeffekt nur noch eien Möglichkeit: Nimm die Testvektoren der failign Tests und vergleiche Deine Ausgabe mit dem vom Test erwarteten.

tumas 
Beitragsersteller
 30.04.2024, 16:03
@KarlRanseierIII

Genau hier liegt mein Problem. Welche Tests fehlschlagen, wird nicht angezeigt. Es wird lediglich die Fehlermeldung geteilt, dass für einige der Tests falsche Indizes zurückgegeben wurden - weitere Informationen werden nicht geteilt.

Du aktualisiert nearestindex basierend auf der Bedingung difference < currentSmallest. Dies sieht korrekt aus, aber die darauf folgende Bedingung (else if (difference == currentSmallest)) könnte Probleme verursachen. Die innere Bedingung vergleicht Math.abs(value - nearestindex) mit Math.abs(value - middle), was inkorrekt ist, da nearestindex ein Index und kein Wert aus sortedData ist. Die korrekte Implementierung sollte Math.abs(value - sortedData[nearestindex]) sein.

else if (difference == currentSmallest) {
  if(Math.abs(value - sortedData[nearestindex]) > Math.abs(value - sortedData[middle])) {
    nearestindex = middle;
  }
}
Woher ich das weiß:Berufserfahrung

tumas 
Beitragsersteller
 30.04.2024, 16:05

Das stimmt, habe ich ausgebessert, löst jedoch weiterhin nicht die fehlgeschlagenen Testcases.

Du hast vergessen, zu prüfen, ob der benachbarte Wert auch tatsächlich näher am gesuchten Wert liegt oder vielleicht der erste gefundene Wert schon der am nächsten liegende ist.