题解 | #数字在升序数组中出现的次数#
数字在升序数组中出现的次数
http://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2
总结了三个方法:
-
第一个方法: 利用
indexOf()
和lastIndexOf()
但是时间复杂度 O(n) 不推荐~ -
第二个方法: 投机取巧 时间复杂度 O(logN) 符合题目要求
-
第三个方法: 第三个方法: 二分查找第一个索引和最后一个索引 时间复杂度O(logN)
现在直接上代码,看注释就能明白:
代码
第一个方法: 时间复杂度 O(n)
function GetNumberOfK(data, k)
{
// write code here
// 第一个方法: 利用Api 时间复杂度 O(n)
return findIndex(data, k)
}
// 第一个方法: 利用Api 时间复杂度 O(n)
// indexOf的操作时间复杂度是O(n) 所以以下不是最优解
function findIndex(data, k) {
let firstIndex, lastIndex, count = 0;
firstIndex = data.indexOf(k)
lastIndex = data.lastIndexOf(k)
if(firstIndex !== -1) {
count = lastIndex - firstIndex + 1
}
return count
}
module.exports = {
GetNumberOfK : GetNumberOfK
};
第二个方法: 时间复杂度 O(logN)
function GetNumberOfK(data, k)
{
// write code here
// 第二个方法: 投机取巧 时间复杂度 O(logN) 符合题目要求
return insertIndex(data, k + 0.1) - insertIndex(data, k - 0.1)
}
// 第二个方法: 投机取巧
// 题目给的是整数,我可以取这个整数的浮点数
// 把3加减0.1之后 利用二分法搜索k-0.1和k+0.1这两个数应该插入的位置
function insertIndex(data, k) {
let left = 0,
right = data.length - 1;
while(left <= right) {
let mid = left + ((right - left) >> 1)
if(data[mid] < k) {
left = mid + 1
} else if (data[mid] > k) {
right = mid - 1
}
}
return left
}
module.exports = {
GetNumberOfK : GetNumberOfK
};
第三个方法: 时间复杂度 O(logN)
主要思路是当mid等于k时,判断左右是否还有相同的数。
function GetNumberOfK(data, k)
{
// write code here
// 第三个方法: 二分查找第一个索引和最后一个索引 时间复杂度O(logN)
let first = firstIndex(data,k),
last = lastIndex(data, k);
if(first === -1 || last === -1) return 0;
return last - first + 1;
}
// 第三个方法: 找第一个和最后一个索引
function firstIndex(data, k) { // 第一个索引
let left = 0,
right = data.length - 1;
while(left <= right) {
let mid = left + ((right - left) >> 1)
if(data[mid] < k) {
left = mid + 1
}
if(data[mid] > k) {
right = mid - 1
}
if(data[mid] === k) {
if(data[mid-1] !== k){ // mid - 1 看左边是否还有相同的数
return mid
} else {
right = mid - 1 // 注意: 继续只寻找左边
}
}
}
return -1
}
function lastIndex(data, k) {// 最后一个索引
let left = 0,
right = data.length - 1;
while(left <= right) {
let mid = left + ((right - left) >> 1)
if(data[mid] < k) {
left = mid + 1
}
if(data[mid] > k) {
right = mid - 1
}
if(data[mid] === k) {
if(data[mid+1] !== k){ // mid + 1 看右边是否还有相同的数
return mid
} else {
left = mid + 1 // 注意: 继续只寻找右边
}
}
}
return -1
}
module.exports = {
GetNumberOfK : GetNumberOfK
};