剑指offer——数字在排序数组中出现的次数
1 题目描述
统计一个数字在排序数组中出现的次数。
2 我的思路
很简单的一个思路是:
- 对数组进行排序:利用
sort()
函数对数组进行递增排序; - 增加一个计数器
count
; - 利用
for
循环对数组进行遍历,若遍历元素大于数字k
,则break
,跳出for
循环;若遍历元素等于数字k
,计数器加1count++
。
3 代码
import java.util.Arrays;
public class Solution {
public int GetNumberOfK(int [] array , int k) {
Arrays.sort(array);
int count=0;
for(int i=0;i<array.length;i++){
if(array[i]>k)
break;
if(array[i]==k)
count++;
}
return count;
}
}
4 其它思想
利用二分查找:最后一个相等元素下标last
减去第一个相等元素下标first
再加一:last-first+1
,即为元素出现个数。
二分查找思想:有序的序列,每次都是以序列的中间位置的数来与待查找的关键字进行比较,每次缩小一半的查找范围,直到匹配成功。
一个情景:将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
优缺点:
优点是比较次数少,查找速度快,平均性能好;
其缺点是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
使用条件:查找序列是顺序结构,有序。
使用二分查找的代码:
1 递归实现:
public static int recursionBinarySearch(int[] arr,int key,int low,int high){
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
int middle = (low + high) / 2; //初始中间位置
if(arr[middle] > key){
//比关键字大则关键字在左区域
return recursionBinarySearch(arr, key, low, middle - 1);
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
return recursionBinarySearch(arr, key, middle + 1, high);
}else {
return middle;
}
}
2 非递归实现:
public static int commonBinarySearch(int[] arr,int key){
int low = 0;
int high = arr.length - 1;
int middle = 0; //定义middle
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
while(low <= high){
middle = (low + high) / 2;
if(arr[middle] > key){
//比关键字大则关键字在左区域
high = middle - 1;
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
low = middle + 1;
}else{
return middle;
}
}
return -1; //最后仍然没有找到,则返回-1
}
5 利用二分查找实现该题的代码
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int length=array.length;
if(length==0)
return 0;
int first=getFirst(array,k,0,length-1);
int last=getLast(array,k,0,length-1);
if(last!=-1 && first!=-1){
return last-first+1;
}
return 0;
}
//练习递归写法
private int getFirst(int [] array,int k,int start,int end){
if(end<start)
return -1;
int mid=(end+start)>>1;// 等价于mid=(end-start)/2;
if(k<array[mid]){
return getFirst(array,k,start,mid-1);
}else if(k>array[mid]){
return getFirst(array,k,mid+1,end);
}else if(mid-1>=0 && k==array[mid-1]){
return getFirst(array,k,start,mid-1);
}else{
return mid;
}
}
//练习非递归写法
private int getLast(int [] array,int k,int start,int end){
if(end<start)
return -1;
int mid=(end+start)>>1;
// 等价于mid=(end+start)/2;
while(start<=end){
if(k<array[mid]){
end=mid-1;
}else if(k>array[mid]){
start=mid+1;
}else if(mid<array.length-1 && k==array[mid+1]){
start=mid+1;
}else{
return mid;
}
mid = (end+start) >> 1;
// 等价于mid=(end+start)/2;
}
return -1;
}
}