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

剑指 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

解题思路

方法一

代码冗余,并且测试用例有一种情况没通过

解答失败:
测试用例:[5,7,7,8,8,10]
6
测试结果:1
期望结果:0

--------------> 有BUG

    public int search_1(int[] nums, int target) {
    
    
        int start = 0, end = nums.length - 1;
        int count_start = 0,count_end = 0;
        int res;
        for (int i = 0; i < nums.length - 1; i++) {
    
    
            int mid = (end - start) /2 + start;
            if (nums[mid] == target){
    
    
                count_start = mid;
                count_end = mid;

                if (nums[count_start] == target){
    
    
                    count_start --;
                }else if (nums[count_end] == target){
    
    
                    count_end ++;
                }
            }else if (nums[mid] < target){
    
    
                start = mid + 1;
            }else if (nums[mid] > target){
    
    
                end = mid - 1;
            }
        }
        res = count_end - count_start + 1;
        return res;
    }

方法二:

一个数的出现次数 = 这个数的开始下标 -下一个数的开始下标

由于数组 nums 中元素都为整数,因此可以分别二分查找 target 和 target +1 的右边界,将两结果相减并返回即可。

public int search_2(int[] nums,int target){
    
    
        if (nums == null){
    
    
            return 0;
        }
        return binarySearch(nums,target + 1) - binarySearch(nums,target);
    }

    private int binarySearch(int[] nums, int target) {
    
    
        int leftIndex = 0;
        int rightIndex = nums.length - 1;
        while (leftIndex <= rightIndex){
    
    
            int midIndex = leftIndex + (rightIndex - leftIndex) /2;
            if (nums[midIndex] < target){
    
    
                leftIndex = midIndex + 1;
            }else {
    
    
                rightIndex = midIndex - 1;
            }
        }
        return leftIndex;
    }

方法三:

初始化:low = 0, high = nums.length - 1.
当low≤high时递归二分查找:
mid = (low + high) / 2
若nums[mid] == target,[low, mid - 1]和[mid + 1, high]都有可能还有target,因为存在重复元素,继续递归查找。
若nums[mid] < target,说明target只可能出现在区间[mid + 1, high],继续递归查找。
若nums[mid] > target,说明target只可能出现在区间[low, mid - 1],继续递归查找。
算法结束,返回计数器的值

  int cnt = 0; //计数器
    public int search(int[] nums,int target){
    
    
       helper(nums,target,0,nums.length - 1);
       return cnt;

    }
    private void helper(int[] nums, int target, int low, int high) {
    
    
        if (low <= high){
    
    
            int mid = low + (high - low) /2;
            if (nums[mid] == target){
    
    
                cnt++; //计数一次
                helper(nums,target,low,mid - 1);
                helper(nums,target,mid + 1,high);
            }else if (nums[mid] > target){
    
    
                helper(nums,target,low,mid - 1);
            }else{
    
    
                helper(nums,target,mid + 1,high);
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_35655602/article/details/114239775
今日推荐