我正在尝试修改递归二进制搜索功能,以便在给定数组包含该元素的倍数的情况下找到该元素的最左侧索引。
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
我试过改变计算mid到(hi + lo - 1)/ 2的方法,它适用于40,得到索引3,但是20得到索引2。
答案 0 :(得分:1)
您需要检查if(key == a[mid])
。如果它相等,则需要检查左侧部分中的最后一个元素是否相同,直到找到不同的元素。
在向左或向右分支之前应进行以下检查
if (key == a[mid]) {
while (--mid >= 0) {
if (key != a[mid]) {
break;
}
}
return ++mid;
}
答案 1 :(得分:0)
问题在于最后一行:
else return mid;
您的列表包含重复项,因此mid可能不是最左边的匹配项。所以试试:
else {
while(--mid>=0) {
if (a[mid]!=key) break;
}
return mid+1;
}