剑指 Offer 53 - I. 在排序数组中查找数字 I(C++) 二分法

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

示例 1:

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

示例 2:

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

限制:

0 <= 数组长度 <= 50000

注意:本题与主站 34 题相同(仅返回值不同):https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

解题思路

查找到target在nums出现的位置

假设存在边界为 left 和 right, 满足 nums[left] < target && nums[right] > target
我们要找到满足条件最大的left和最小的right
对应的窗口大小就是 right - left - 1;
具体实现:

用二分法,两次去查找左边和右边界
优化: 简化代码,其实可以都用左边界,而有边界求解改为 target+1的左边界求解, 对应窗口变为 right-left (无需1)

class Solution {
    
    
private:
    // 找到>=target的左边界,就是满足 nums[i] >= target里的i的最小值
    inline int BinaryLeft(vector<int>& nums, int target)
    {
    
    
        int l = 0;
        int r = nums.size() -1 ;
        int m = 0;
        while (l <= r)
        {
    
    
            m = (l+r) >> 1;
            if (nums[m] < target)
            {
    
    
                l = m + 1;
            }
            else//nums[m] >= target
            {
    
    
                r = m - 1;
            }
        }
        // cout << target << " " << l << endl;
        return l;
    }

public:
    int search(vector<int>& nums, int target) {
    
    
        // 题目假设存在target,无法额外判断
        // 二分查找都是left边界,等于是前开后闭,这里计算窗口无需额外减1
        return BinaryLeft(nums, target+1) - BinaryLeft(nums, target);
    }
};

代码实现的逻辑:

以nums = [5,7,7,8,8,10], target = 8为例:
1-、m=2,nums[m] < target,L=3;
2-、m=4;nums[4] >=8,R=3
最后返回L3,
以nums = [5,7,7,8,8,10], target = 9为例:
1-、m=2,nums[2] <9,L=3;
2-、m=4;nums[4] <9,L=5
3、m=5,nums[5]>=9,R=4
返回L
5
最后得到值为:5-3=2

猜你喜欢

转载自blog.csdn.net/qq_30457077/article/details/114646477
今日推荐