Loading

Medium | LeetCode 34 | 剑指 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

限制:

0 <= 数组长度 <= 50000

使用二分法分别找到最左边界和最右边界即可。二分法本质上是一种减法思想, 利用了数组有序的特性, 每次通过二分都能排除掉一半。

public int search(int[] nums, int target) {
    if (nums.length == 0) {
        return 0;
    }
    int fisrstPosition = findFirstPostion(nums, target);
    if (fisrstPosition == -1) {
        return 0;
    }
    int lastPosition = findLastPosition(nums, target);
    return lastPosition - fisrstPosition + 1;
}

// 找target出现的最左边界
private int findFirstPostion(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left < right) {
        int mid = (left + right) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else {
            // 当mid值等于target值时, 当前mid的值也是还要保留的,
            // 因为当前的mid值可能就是左边界, 也因此是要往左找
            // 既然保留mid作为right, 所以取mid值, 一定是下取整
            right = mid;
        }
    }
    if (nums[left] != target) {
        return -1;
    }
    return left;
}
// 找target出现的最右边界
private int findLastPosition(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left < right) {
        int mid = (left + right + 1) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else {
            // 当mid值等于target值时, 当前mid的值也是还要保留的,
            // 因为当前的mid值可能就是右边界, 也因此是要往右找
            // 既然保留mid作为left, 所以取mid值, 一定是上取整
            left = mid;
        }
    }
    return left;
}
posted @ 2021-01-17 12:03  反身而诚、  阅读(50)  评论(0编辑  收藏  举报