Set*_*eno 10 java algorithm binary-search time-complexity
我正在学习考试,并发现了这个问题.
您将获得一个排序的整数数组,例如:
{-5, -5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 67, 67, 99}
Run Code Online (Sandbox Code Playgroud)
写一个方法:
Public static int count (int[] a, int x)
Run Code Online (Sandbox Code Playgroud)
返回数字'x'在数组中的次数.
例如:
x = -5, it returns 2
x = 2, it returns 5
x = 8, it returns 0
Run Code Online (Sandbox Code Playgroud)
我需要尽可能高效地写它,请不要给我答案(或者如果你愿意的话写下来,但我不会看),我的想法是做二分搜索,然后去两边(向后)我找到的值和索引号,返回正确的答案,我的问题是:
如果是这样 - 那我为什么要进行二分搜索呢?
有两种解决方案:
1)可以执行Binary Search,但是要保持发现第一次出现的不变性。然后进行线性搜索。这将是Theta(log n + C),其中C是计数。
乔恩·本特利(Jon Bentley)的《编程珍珠》(Programming Pearls)写的很好,他提到寻找首次发生实际上比寻找任何发生更为有效。
2)您还可以进行两个二进制搜索,一个用于第一次出现,一个用于最后一次,并取下索引的差。这将是Theta(log n)。
您可以根据C的期望值决定采用哪种解决方案。如果C = o(log n)(是o小),则寻找第一个出现的位置并进行线性搜索会更好。否则,进行两个二进制搜索。
如果您不知道C的期望值,那么使用解决方案2可能会更好。
二元搜索找到第一次出现.进行二分查找以找到最后一次出现.出现次数等于找到的2个索引之间的数字数.
public class Main {
public static void main(String[] args){
int[] arr = {-5, -5, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 67, 67, 99};
int lo = getFirst(arr, -5);
if(lo==arr.length){ // the number is not present in the array.
System.out.println(0);
}else{
int hi = getLast(arr, -5);
System.out.println((hi-lo+1));
}
}
// Returns last occurence of num or arr.length if it does not exists in arr.
static int getLast(int[] arr, int num){
int lo = 0, hi = arr.length-1, ans = arr.length;
while(lo<=hi){
int mid = (lo+hi)/2;
if(arr[mid]==num){
ans = mid;
lo = mid+1;
}else if(arr[mid]<num){
lo = mid+1;
}else if(arr[mid]>num){
hi = mid-1;
}
}
return ans;
}
// Returns first occurence of num or arr.length if it does not exists in arr.
static int getFirst(int[] arr, int num){
int lo = 0, hi = arr.length-1, ans = arr.length;
while(lo<=hi){
int mid = (lo+hi)/2;
if(arr[mid]==num){
ans = mid;
hi = mid-1;
}else if(arr[mid]<num){
lo = mid+1;
}else if(arr[mid]>num){
hi = mid-1;
}
}
return ans;
}
}
Run Code Online (Sandbox Code Playgroud)