力扣:53 - I. 在排序数组中查找数字 I

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

描述

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

  • 示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
复制代码
  • 示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
复制代码
  • 提示
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109
复制代码
  • 进阶:
  • 如果给定的数组中含有负数会发生什么?问题会产生何种变化?如果允许负数出现,需要向题目中添加哪些限制条件?

解析

由题目可知,在排序数组中,寻找target,是否在数组存在,已经存在的次数;如果没有存在就返回0,否则就返回存在的次数。

直观的思路肯定是从前往后遍历一遍。用两个变量记录第一次和最后一次遇见 \textit{target}target 的下标,但这个方法的时间复杂度为 O(n)O(n),没有利用到数组升序排列的条件。

由于数组已经排序,因此整个数组是单调递增的,我们可以利用二分法来加速查找的过程。

如果存在target在数组中存在,那么他在数组中可以用下标给标示出来,那么我们可以找出数组中target出现的左边界left和有边界right,即返回的次数就是right-left-1。

示例

class Solution {
    public int search(int[] nums, int target) {
       //获取数组长度
       int length=nums.length;
       //因为这个数组里面的数字是排序好的,
       //所以通过二分法来确定target对应在数组中出现的区域,区域内都是target值
       int i=0;
       int j=length-1;
        //先确定目标区域的右边界
       while(i<=j){
           int m=(i+j)/2;
           //if存在说明target所在范围在二分法的右边
           if(nums[m]<=target){
               i=m+1;
           }else{
               j=m-1;
           }
       }
​
       int right=i;
       if(j>0&&nums[j]!=target){
           return 0;
       }
       i=0;j=length-1;
       //确定目标的左边界
       while(i<=j){
           int m=(i+j)/2;
           //target的左边界必然小于target的值
           if(nums[m]<target){
               i=m+1;
           }else{
               j=m-1;
           }
       }
       int left=j;
        //右区间-左区间-1 就是含的个数
       return right-left-1;
    }
}
​
复制代码

运行结果:

执行结果:通过

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:41.1 MB, 在所有 Java 提交中击败了81.55%的用户

猜你喜欢

转载自juejin.im/post/7035632684139282469
今日推荐