[剑指offer] 数字在排序数组当中出现的次数

时间:2022-11-21 11:04:37

[剑指offer] 数字在排序数组当中出现的次数 P221

11122222333

使用二分搜索查找target的开始indexbegin和结束indexend,则个数是indexend - indexbegin + 1;

找到开始位置

getBeginIndex(int [] num, int target):
  int left =0;

  int right = num.length-1;

  while(left<=right){

    if(left<right) return -1;没有这个元素target

    int mid = (left + right)/2;

    if(num[mid]==target){

       if(mid==0||num[mid-]!=target) return mid;

       right = mid-1;

    }else if(num[mid]> target){

       right = mid-1;

    }else{

       left = mid+1;

    }

  }

return -1;

找到结束位置

getEndIndex(int [] num ,int target):

  int left = 0;

  int right = num.length-1;

  while(left<=right):

    if(left>right) return -1;

    int mid = (right+left)/2;

    if(num[mid]==target){

       if(mid==num.length-1||num[mid+1]!=target) return mid;

      left = mid+1;

    }else if(num[mid]>target){

       right = mid-1;

    }else{

       left = mid+1;

    }

return -1;

调用上面的方法求左右边界

targetlength(int [] num,int target):

  int left = getBeginIndex(num,target);

  int right = getEndIndex(num,target);

  if(left!=-1&&right!=-1):

    return[0]=left;

    return[1]=right;

  else

    return error;

end

 

上面两个方法都是O(logN)的,所以总的复杂度是O(logN)

 leetcode 当中的一个题目使用这里的方法

search for a range

 1 public class Solution {
 2     private int searchL(int [] nums,int target){
 3         //to reduce the thinking and make the problem clear, the corner case should be 
 4         // resolved first.
 5         if(target<nums[0]||target>nums[nums.length-1]){
 6             return -1;
 7         }
 8         int left = 0;
 9         int right = nums.length-1;
10         while(left<=right){
11             int mid = (left+right)/2;
12             if(nums[mid]==target){
13                 if(mid==0||nums[mid-1]!=target) return mid;
14                 right = mid-1;
15             }else if(nums[mid]>target){
16                 right = mid-1;
17             }else{
18                 left = mid+1;
19             }
20         }
21         return -1;
22     }
23     private int searchR(int [] nums,int target){
24         //to reduce the thinking and make the problem clear, the corner case should be 
25         // resolved first.
26         if(target<nums[0]||target>nums[nums.length-1]){
27             return -1;
28         }
29         int left = 0;
30         int right = nums.length-1;
31         while(left<=right){
32             int mid = (left+right)/2;
33             if(nums[mid]==target){
34                 if(mid==nums.length-1||nums[mid+1]!=target) return mid;
35                 left = mid+1;
36             }else if(nums[mid]>target){
37                 right = mid-1;
38             }else{
39                 left = mid+1;
40             }
41         }
42         //when stop the right index must be larger than the right index
43         //the left index can not stop on the index whose value equals target
44         //so we just need to consider right index here
45         return -1;
46     }
47     public int[] searchRange(int[] nums, int target) {
48         int [] res = new int[2];
49         res [0] = searchL(nums,target);
50         res [1] = searchR(nums,target);
51         return res;
52     }
53 }