0
点赞
收藏
分享

微信扫一扫

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



转载本文章请标明作者 ​​《Darwin的程序空间》​​


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

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


题目

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

示例:

输入: 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;
}
}

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

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


举报

相关推荐

0 条评论