剑指offer | 面试题53 - I.数字在排序数组中出现的次数

转载本文章请标明作者和出处
本文出自《Darwin的程序空间》
本文题目和部分解题思路来源自《剑指offer》第二版

在这里插入图片描述

开始行动,你已经成功一半了,献给正在奋斗的我们

题目

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

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

解题分析

首先我们分析一下题干,一个排序的数组,我们应该下意识的相到,排序的数组,百分之99和二分算法有关系了,再看人家要的是统计出一个数字的出现次数;

大部分的同学此时可能会想,这还不简单,我遍历一遍,把这个数字统计一下个数,完美解决,并且时间复杂度只有O(n),而且因为是排序的,统计到这个数字之后就可以终止循环,完美;

但这种解法,面试官是肯定不会认可的,因为这道题其实隐藏条件就是,时间复杂度最多是O(lgn),而据我所知,已知这种时间复杂度的算法,最出名的就是二分算法了,所以,我们要使用二分算法来解这道题;

而我们已知的二分算法是给一个排序数组和一个数,我们从这个排序数组中找出这个数的索引值,那么怎么应用到这道题里面呢?

其实满足题目我们只需要找到两个索引值即可,就是目标数第一次出现的索引值,和最后一次出现的索引值,两个索引值相减加一即是个数;

那么第一次出现怎么表示呢,就是等于目标值并且左边要不是空,要不是不等于目标值的值的元素;
最后一次呢?那就是等于目标值并且右边要不是空,要不是不等于目标值的值的元素;

所以我们只需要使用二分算法分别找出这两个元素即可,因为两次寻找的时间复杂都是O(lgn),所以加起来还是O(lgn);

代码(JAVA实现)

ps:这里笔者使用的jdk为1.8版本

class Solution {
    public int search(int[] nums, int target) {
        int leftIndex = findLeftIndex(nums, target);
        int rightIndex = findRightIndex(nums, target);
        return rightIndex - leftIndex + 1;
    }

    private int findLeftIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            int num = nums[mid];
            if (num == target && (mid == 0 || nums[mid - 1] != target)) {
                return mid;
            } else if (num == target || num > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return 1;
    }

    private int findRightIndex(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            int num = nums[mid];
            if (num == target && (mid == nums.length - 1 || nums[mid + 1] != target)) {
                return mid;
            } else if (num == target || num < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return 0;
    }
}


喜欢的朋友可以加我的个人微信,我们一起进步
发布了156 篇原创文章 · 获赞 19 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qq_36929361/article/details/104464076