剑指 Offer 53-I. 在排序数组中查找数字 I(Java版本)

剑指 Offer 53-I. 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

限制:0 <= 数组长度 <= 50000
解法1:暴力方法,遍历数组

	public static int search(int[] nums, int target) {
		int c=0;
		for(int i=0;i<nums.length;i++)
		{
			if(nums[i]==target)c++;
		}
		return c;
    }

解法2:二分法
因为题目中数组是排序数组,可以使用二分法,
本来的想法是,二分法找到一个target然后左右搜索一共有几个target,但是如果有n个target的话,时间复杂度和暴力算法一样了,并不简便。
我就想到了另一种,用二分法分别找到target最左面和最右面的一个,下标相减加1即可
如何判断target是最左面或者是最右面的呢
假设已经找到nums[mid]==target,判断是最左面的target,nums[mid-1]!=target,如果是数组开头的一个肯定是最左面的一个,所以判断条件就是:mid==0||nums[mid-1]!=target。判断target是不是最右面的一个同理:mid==nums.length-1||nums[mid+1]!=target
Java代码如下:

public static int search(int[] nums, int target) {
		int left=-1;
		int right=-1;
		int start=0;
		int end=nums.length-1;
		while(start<=end){//left
        	int mid = (end+start)/2;
            if(nums[mid]==target){
                if(mid==0||nums[mid-1]!=target) {
                	left=mid;
                	break;
                }
                else end = mid-1;//target左面还是target,第一个target应该是是在[start,mid-1]区间
            }
            else if(nums[mid]>target) end = mid-1;
            else start = mid+1;
        }
		start=0;
		end=nums.length-1;
		while(start<=end){//right
        	int mid = (end+start)/2;
            if(nums[mid]==target){
                if(mid==nums.length-1||nums[mid+1]!=target)//
                {
                	right=mid;
                	break;
                }
                else start = mid+1;
            }
            else if(nums[mid]>target) end = mid-1;
            else start = mid+1;
        }
		if(left!=-1&&right!=-1)
			return right-left+1;
		else return 0;
	}

你可能感兴趣的:(剑指 Offer 53-I. 在排序数组中查找数字 I(Java版本))