我正在尝试修改递归二进制搜索函数,以便在数组包含该元素的倍数的情况下,它将找到该元素的最左侧索引。

import java.util.*;
import java.util.Arrays;
import java.io.File;
import java.io.IOException;

public class LeftmostBinarySearch {

    private static int myBinarySearch(int key, int[] a, int lo, int hi) {
    if (lo > hi) {
        return -1;
    }
    int mid = lo + (hi - lo) / 2;
    if (key < a[mid]) {
        return myBinarySearch(key, a, lo, mid - 1);
    } else if (key > a[mid]) {
        return myBinarySearch(key, a, mid + 1, hi);
    } else {
        return mid;
    }
}

    public static int myBinarySearch(int key, int[] a) {
    return myBinarySearch(key, a, 0, a.length - 1);
}

    public static void main(String[] args) throws IOException {
        String fileName = args[0] + ".txt";
        System.out.println(fileName);
        Scanner scanner = new Scanner(new File(fileName));
        int[] data = new int[7];
        int i = 0;
        int j = 0;

        while (scanner.hasNextInt()) {
            data[i] = scanner.nextInt();
            i++;
        }
        Arrays.sort(data);
        System.out.format("%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s", " 0",
                "  ", " 1", "  ", " 2", "  ", " 3", "  ", " 4", "  ", " 5", "  ", " 6\n");
        System.out.format("%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s", data[j],
                "  ", data[j + 1], "  ", data[j + 2], "  ", data[j + 3], "  ",
                data[j + 4], " ", data[j + 5], "  ", data[j + 6] + "\n");

        int input = new Scanner(System.in).nextInt();

        while ((Integer) input != null) {
            int key = input;
            System.out.println(data[0]);
            if (myBinarySearch(key, data) != -1) {
                System.out.println(input + " found: "
                        + myBinarySearch(key, data));
            }
            input = new Scanner(System.in).nextInt();
        }
    }
}


我从中得到的输出是:

C:\Users\Shirley\algs4>java LeftmostBinarySearch mydata
 0   1   2   3   4   5   6
10  20  20  30  40  40  40
10
10 found: 0
20
20 found: 1
30
30 found: 3
40
40 found: 5


我试过更改中值到(hi + lo-1)/ 2的计算方式,它适用于40,给出索引3,但适用于20,给出索引2。

最佳答案

问题出在最后一行:

else return mid;


您的列表包含重复项,因此mid可能不是最左边的匹配项。因此,请尝试:

else {
  while(--mid>=0) {
    if (a[mid]!=key) break;
  }
  return mid+1;
}

10-06 11:38