描述
题目描述
统计一个数字在升序数组中出现的次数。
示例
输入:[1,2,3,3,3,3,4,5],3 返回值:4
引言
看到有序数组,就要立马想到用二分查找,一般都能解决问题并且优化时间复杂度
知识点:数组,二分法
难度:⭐⭐
题解
解题思路
二分查找法,获取目标值的前后下标,即获取目标值在数组中的长度
关键是运用微妙的 + 0.5 和 - 0.5,找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度
方法一:二分法
图解

算法流程:
- 二分查找法,返回 num 在 arr 的第一个下标
- 如果找不到目标值,则返回第一个大于目标值的数的下标
- 通过浮点数,只需要找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度
Java 版本代码如下:
public class Solution {
public int GetNumberOfK(int [] array , int k) {
// 通过浮点数,只需要找出数组中第一个大于k和最后一个小于k的数的下标
// 相减就可以获得k在数组中的长度
return helper(array, k + 0.5) - helper(array, k - 0.5);
}
// 找到num在arr的第一个下标
int helper(int[] arr, double num) {
// 二分法
int lo = 0, hi = arr.length - 1;
int mid = 0;
// 该二分查找法,返回num在arr的第一个下标
// 如果找不到目标值,则返回第一个大于目标值的数的下标
while(lo <= hi) {
// 这种写法可以避免整型相加时溢出
mid = lo + ((hi - lo) >> 1);
if(arr[mid] < num) {
lo = mid + 1;
} else if(arr[mid] > num) {
hi = mid - 1;
}
}
// 找到num在arr的第一个下标
// 如果找不到目标值,则返回第一个大于目标值的数的下标
return lo;
}
} Python 版本代码如下:
class Solution:
def GetNumberOfK(self, data, k):
# write code here
n = len(data)
left, right = 0, n - 1
while left <= right:
mid = (left + right) // 2
if data[mid] < k:
left = mid + 1
elif data[mid] > k:
right = mid - 1
else:
right = mid - 1
l = right
left, right = 0, n - 1
while left <= right:
mid = (left + right) // 2
if data[mid] < k:
left = mid + 1
elif data[mid] > k:
right = mid - 1
else:
left = mid + 1
r = left
cur = r - l - 1
return cur if cur > 0 else 0 复杂度分析:
时间复杂度 O(logN):二分法通常时间复杂度都是O(logN)
空间复杂度 O(1):只用到整数型的数据类型,常数项级别
总结:求解升序数组的题目一般都可以用二分法解决
方法二:暴力解法
算法流程:
- 遍历、计数即可
Java 版本代码如下:
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int count = 0;
for(int a : array){
if(k == a){
count++;
}
}
return count;
}
}Python 版本代码如下:
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
# write code here
if not data:
return 0
return data.count(k)复杂度分析:
时间复杂度 O(N):遍历数组,长度为 N
空间复杂度 O(1):只用到整型类型

京公网安备 11010502036488号