(剑指offer 53-1 在排序数组中查找数字1)2021.1-10

//统计一个数字在排序数组中出现的次数。 
//
// 
//
// 示例 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/ 
// Related Topics 数组 二分查找 
// 👍 85 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int search(int[] nums, int target) {
         // //今天刷题开始有一点感觉了,刷题还是应该按照分类来刷,按照详细分类,如leetcode总结如下
        // //1.二分查找 2.二叉树、链表 3.递归、DFS 4.双指针 4.BFS、拓扑排序 6.hash表 7.动态规划 8.滑动窗口 9.字典树 
        // //备注:先按照分类刷剑指offer,掌握不牢靠再刷top100和面试精选
        // //这个题是一个典型的二分查找,我的思路先定位到那个数字然后,收缩低位和高位指针,计算多少个数字,无奈,时间太慢
        // int low = 0;int res = 0;int high = nums.length - 1;
        // while(low < high){
        //     int mid = (low + high)/2;
        //     if(nums[mid] < target){ 
        //         low = mid + 1;
        //     }else if(nums[mid] > target){
        //         high = mid - 1;
        //     }else{
        //         //如果命中,先结果集+1,然后收缩低位、高位指针
        //         res++;
        //         low = mid - 1;
        //         high = mid + 1;
        //         //当无论哪一个低位、高位所对应的元素不是目标结果时,就退出循环,最后返回结果集
        //         while(nums[low] == target || nums[high] == target){
        //             if(nums[low] == target){
        //                 low--;
        //                 res++;
        //             }
        //             if(nums[high] == target){
        //                 high++;
        //                 res++;
        //             }
        //         }
        //     }
        // }
        // return res;//最坏时间复杂度就是,数组中元素全部相等,O(nlogn),感觉还不如,遍历一遍暴力解法


        //哎,官方解释,大佬还是大佬,官方解释是寻找目标数字数组的前后两个指针指向的位置,相减即可

        //二分查找的题,太坑了,很不容易写完全正确,需要考虑左右开闭空间,同时考虑while循环判断条件都是相等的情况,高低位指针赋值也需要考虑
        int low = 0;int high = nums.length - 1;
        //找右边界
        while(low <= high){
            int mid = (high - low)/2 + low;
            if(nums[mid] <= target){
                low = mid + 1;
            }else if(nums[mid] > target){
                high = mid - 1;
            }
        }
        int right = low;
        //注意这里如果有边界的前一个数不是target则提前返回,这里的作用是找不到直接减少第二次二分查找
        if(high >= 0 && nums[high] != target) return 0;
        //找左边界
        // int i = 0;int j = nums.length - 1;//这里可以优化,不需要再开一个高低位指针,且高位指针不需要重置,减少一次二分
        //  while(i <= j){
        //     int k = (j - i)/2 + i;
        //     if(nums[k] < target){
        //         i = k + 1;
        //     }else if(nums[k] >= target){
        //         j = k - 1;
        //     }
        // }
        // int left = j;
        low = 0;//这里可以优化,不需要再开一个高、低位指针,且高位指针不需要重置,减少一次二分
        while(low <= high){
            int mid = (high - low)/2 + low;
            if(nums[mid] < target){
                low = mid + 1;
            }else if(nums[mid] >= target){
                high = mid - 1;
            }
        }
        int left = high;
        return right - left - 1;
        //时间复杂度为O(logn)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值