二分查找适用场景:查找一个数字;统计某个数字出现次数。
题目要求
解题思路
看到题目最容易想到的是哈希,用哈希表去解这个问题应该是最很简单的,但面试官肯定希望我们用二分查找去解决。
二分查找的解法
- 定义left,right边界值;
- 取中间元素mid,如果target > mid,说明要找的值在右半部分,所以left = mid+1;
- 如果target < mid,说明值在左半部分,right = mid - 1;
- 如果正好target = mid,找到了该值,如果有重复元素,一定在mid的相邻两侧,再继续对这种情况判断;
- 如果target > left,让left往右边移动一位,left++;
- 如果target < right,让right往左边移动一位,right–;
- 直到left,right都移到相同的值,right - left + 1 就是该值的个数;
//二分查找
var search = function(nums, target) {
let left = 0;
let right = nums.length - 1;
while(left <= right){ //注意left <= right,因为有重复值存在,所以存在等于的情况
let mid = Math.floor((left + right)/2)
if(target > nums[mid]){
left = mid + 1;
}else if(target < nums[mid]){
right = mid - 1;
}else{
if(nums[left] == nums[right]){
return right - left + 1
}
if(target > nums[left]){
left++
}
if(target < nums[right]){
right--
}
}
}
return 0
};
下面是哈希表解法
- 创建map,用哈希表的键值对去存储链表节点;
- 遍历链表,哈希表的key储存链表节点的值,value记录该节点出现的次数;
- 查找map中是否存在要查找的节点,返回对应节点的值。
//哈希表
var search = function(nums, target) {
if(!nums) return 0;
let map = new Map();
for(let i = 0;i < nums.length;i++){
if(map.has(nums[i])){
let count = map.get(nums[i])
count += 1;
map.set(nums[i],count)
}else{
map.set(nums[i],1)
}
}
for(let [key,value] of map){
if(key === target){
return value
}
}
return 0
};