在微软的现场采访中提到了这一点。
计算数组中给定键的出现次数。
我回答了线性搜索,因为元素可能会分散在 阵列。说密钥在开头和结尾都有。所以我们 需要扫描整个阵列。
接下来他询问阵列是否已排序?
想了一会儿,说我会再次使用线性搜索。因为 密钥的重复(如果存在)可以在阵列中的任何位置。作为一个 优化我还说如果第一个和最后一个数组元素是相同的 可以将数组长度作为答案。
两种情况下我的分析是否正确?
示例:
Input = [0 0 1 1 1 2 2 3 3], key = 1, Answer = 3
Input = [0 0 2 2 3 3], key = 1, Answer = 0
答案 0 :(得分:28)
对于未排序的数组,我们除了线性搜索之外没有什么可做的。
对于排序数组,您可以使用略微修改的二进制搜索在O(logN)
中执行此操作:
key
,将其称为f
。key
,将其称为l
。key
中存在l-f+1
是答案。查找第一次出现:
arr[i]
是第一次出现key
iff
arr[i] == key
和
i == 0
(这是第一个元素
数组)或 arr[i-1] != key
(这不是第一个
数组元素和元素
它的左边是不同的)您可以稍微修改二进制搜索以查找第一次出现。
在二进制搜索中,当您找到arr[mid] == key
时终止搜索。
修改条件以终止搜索如果您发现 第一个 ,而不是 任何 。
算法:
low = 0
high = arrSize - 1
while low <= high
mid = (low + high) / 2
//if arr[mid] == key // CHANGE
if arr[mid] == key AND ( mid == 0 OR arr[mid-1] != key )
return mid
//else if ( key < arr[mid] ) // CHANGE
else if ( key <= arr[mid] )
high = mid - 1
else
low = mid + 1
end-if
end-while
return -1
同样,您可以找到最后一次出现。
答案 1 :(得分:8)
有一次,我将提出一个用C ++实现的方法。
size_t count(std::vector<int> const& vec, int key)
{
auto p = std::equal_range(vec.begin(), vec.end(), key);
return std::distance(p.first, p.second);
}
equal_range
使用二分搜索,结果相当于:
std::make_pair(std::lower_bound(vec.begin(), vec.end(), key),
std::upper_bound(vec.begin(), vec.end(), key);
但是实现应该稍微加快一点,即使它们都在O(log N)中(就比较数而言)。
答案 2 :(得分:3)
#include<stdio.h>
int binarysearch(int a[],int n,int k,bool searchfirst){
int result=-1;
int low=0,high=n-1;
while(low<=high){
int mid=(low+high)/2;
if(a[mid]==k) {
result=mid;
if(searchfirst)
high=mid-1;
else
low=mid+1;
}
else if(k<a[mid]) high=mid-1;
else low=mid+1;
}
return result;
}
int main(){
int a[]={1,1,1,2,2,3,3,3,6,6,6,6,6,7,7};
int n=sizeof(a)/sizeof(a[0]);
int x=6;
int firstindex=binarysearch(a,n,x,true);
printf("%d\n",firstindex);
if(firstindex==-1){
printf("elment not found in the array:\n ");
}
else {
int lastindex=binarysearch(a,n,x,false);
printf("%d\n",lastindex);
printf("count is = %d", lastindex-firstindex+1);
}
}
答案 3 :(得分:1)
您可以使用二进制搜索的递归版本
int modifiedbinsearch_low(int* arr, int low, int high , int key)
{
if(low==high) return high ;
int mid = low + (high-low) /2;
if(key > arr[mid] ) { modifiedbinsearch_low(arr,mid + 1 , high,key); }
else { modifiedbinsearch_low(arr,low,mid,key); }
}
int modifiedbinsearch_high(int* arr, int low, int high , int key)
{
if(low==high) return high ;
int mid = low + (high-low) /2;
if(key < arr[mid] ) { modifiedbinsearch_high(arr,low,mid,key); }
else { modifiedbinsearch_high(arr,mid+1,high,key); }
}
int low = modifiedbinsearch_low( ...)
int high = modifiedbinsearch_high( ...)
(high - low)
给出了键数
答案 4 :(得分:1)
** 时间复杂度 = O(lg N)其中N是数组的大小
** binarySearchXXXXX的参数:**
**
package array;
public class BinarySearchQuestion {
public static int binarySearchFirst(int[] array, int k) {
int begin = 0;
int end = array.length-1;
int mid = -1;
while (begin <= end) {
mid = begin + (end - begin) / 2;
if (array[mid] < k) {
begin = mid + 1;
} else {
end = mid - 1;
}
}
//System.out.println("Begin index :: " + begin + " , array[begin] " + array[begin]);
return (begin <= array.length - 1 && begin >= 0 && array[begin] != k) ? -1 : begin;
// return begin;
}
public static int binarySearchLast(int[] array, int k) {
int begin = 0;
int end = array.length - 1;
int mid = -1;
while (begin <= end) {
mid = begin + (end - begin) / 2;
if (array[mid] > k) {
end = mid - 1;
} else {
begin = mid + 1;
}
}
//System.out.println("Last index end :: " + end + " , array[mid] " + array[end]);
return (end <= array.length - 1 && end >= 0 && array[end] != k) ? -1 : end;
//return end;
}
/**
* @param args
*/
public static void main(String[] args) {
// int[] array = { 0, 1,1,1, 2, 3, 4,4,4,5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5,6,6,6,6, 6, 7, 7, 7,
// 7, 8, 9 };
// int[] array = {-1, 0,1, 1,1,2,3};
int[] array = {1,1,1};
int low = binarySearchFirst(array, 1);
int high = binarySearchLast(array, 1);
int total = (high >= low && low != -1 && high != -1) ? ( high - low + 1 ): 0;
System.out.println("Total Frequency " + total);
}
}
答案 5 :(得分:1)
对于排序部分,O(logN)时间复杂度如何?
int count(int a[], int k, int l, int h) {
if (l>h) {
return 0;
}
int mid = (l+h)/2;
if (k > a[mid]) {
return count(a, k, mid+1, h);
}
else if (k < a[mid]) {
return count(a, k, l, mid-1);
}
else {
return count(a, k, mid+1, h) + count(a, k, l, mid-1) + 1;
}
}
答案 6 :(得分:0)
包数组;
/ * *给定排序数组,查找元素发生的次数。 *二进制搜索O(lgn) * * /
公共类NumberOfN {
static int bSearchLeft(int[] arr, int start, int end, int n){
while(start < end){
int mid = (start + end)>>1;
if(arr[mid] < n){
start = mid + 1;
}else{
end = mid;
}
}
return end;
}
static int bSearchRight(int[] arr, int start, int end, int n){
while(start < end){
int mid = (start + end)>>1;
if(arr[mid] <= n){
start = mid + 1;
}else{
end = mid;
}
}
return end;
}
/**
* @param args
*/
public static void main(String[] args) {
int[] arr = new int[]{3,3,3,3};
int n = 3;
int indexLeft = bSearchLeft(arr, 0, arr.length, n);
int indexRight = bSearchRight(arr, 0, arr.length, n);
System.out.println(indexLeft + " " +indexRight);
System.out.println("Number of occurences: " + (indexRight - indexLeft));
}
}
答案 7 :(得分:0)
我们可以使用Linear和Binary Search来解决这个问题。 但线性搜索将是O(n)。二进制搜索将给出O(Logn)。 因此,使用二进制搜索会更好。 完整的计划是:
public class Test4 {
public static void main(String[] args) {
int a[] = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7};
int x = 6;
System.out.println(fix(a,x));
}
private static int fix(int[] a, int x) {
int res = 0 ;
for (int i = 0; i < a.length; i++) {
int ch = a[i];
if(x == ch) {res++ ;}
}
return res;
}
}
还有另一个跟进问题是:排序数组中给定数字的第一次和最后一次出现。
class Occurence1 {
public static void findFirstAndLast(int a[], int x) {
int first = -1, last = -1;
for (int i = 0; i < a.length; i++) {
if (x == a[i]) {
if (first == -1) {
first = i;
}
// update last
last = i;
} // if
} // for
if (first != -1) {
System.out.println("First Occurrence = " + first);
System.out.println("Last Occurrence = " + last);
}
}// end1
public static void main(String[] args) {
int arr[] = { 1, 2, 2, 2, 2, 3, 4, 7, 8, 8 };
int x = 8;
findFirstAndLast(arr, x);
}
}
在Python中:
def findFirstAndLast(a, x):
first = -1 ; last = -1
for i in range(len(a)) :
if(x == a[i]):
if(first == -1):first = i
# update last if the first contains oter value than -1
last = i
if(first != -1):
print("first => ",first)
print("last =>", last)
a = [1, 2, 3,4, 5, 6, 7, 8, 1, 10, 10]
x = 10
findFirstAndLast(a, x)
答案 8 :(得分:-1)
如果数组未排序,是的,从一端到另一端的线性搜索就像它一样好。
但是,如果对数组进行排序,则可以通过应用二进制或插值搜索技术来比线性时间更好。
将问题视为与“在排序列表中查找数字X”相同,并添加“然后向左和向右扫描以确定X出现的次数”的详细信息。第一部分,搜索,最好在大多数情况下使用二进制或插值搜索。
答案 9 :(得分:-2)
是的,你对于未排序的数组是正确的,但是对于排序的数组,你可以使用二进制搜索找到元素的一个出现,一旦发现一个出现,只扫描相邻的元素,直到找到不匹配然后停止。