今天做一道数组 二分查找的算法题。(题目来源,LeetCode34)
题目
在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组nums
,和一个目标值target
。找出给定目标值在数组中的开始位置和结束位置。
算法的时间复杂度必须是O(logn)级别。
如果数组中不存在目标值,返回[-1,-1]。
思路
- 升序整数数组,且要求时间复杂度为O(logn),则采用二分法对数组进行目标值查找
- 采用防御式编程,数组中不存在时,返回[-1,-1],,若数组长度为0,直接返回[-1,-1];
- 若寻找第一个目标值,没有找到,则表明数组中没有目标值,返回[-1,-1]
二分法写法
写二分法,
首先要明确 数据查找的范围 — [left,right],包含左右边界。
然后要明确,什么时候 终止查找 — left== right时终止查找(当left == right时,要么left对应的值为目标值,要么木有目标值) 或 找到了目标值终止查找
最后要确定,中间值采用向上取整还是向下取整方式选取值,于目标值进行比较
— 查找单个值时,采用向下取整或向上取整都可以,只要整个过程都采用这种取整方式既可以。
当查找值有重复时,查找第一个目标值,采用向下取整,取靠近left的那个。
查找最后一个目标值,采用向上取整,取靠近right的那个。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| function searchTarget(nums,target){ if(!nums || nums.length == 0){ return -1 } let left = 0; let right = nums.length - 1; while(left < right){ let mid = Math.floor(left + (right-left)/2) if(nums[mid] == target){ left = mid break; }else if(nums[mid] < target){ left = mid +1 }else if(nums[mid]>target){ right = mid - 1 } } if(nums[left]== target){ return left }else{ return -1 } }
function searchLeftTarget(nums,target){ if(!nums || nums.length == 0){ return -1 } let left = 0; let right = nums.length - 1;
while(left < right){ let mid = Math.floor(left + (right-left)/2) if(nums[mid]==target){ right = mid }else if(nums[mid] < target){ left = mid + 1 }else if(nums[mid] > target){ right = mid -1 } } if(nums[left] == target){ return left }else{ return -1 } }
function searchRightTarget(nums,target){ if(!nums || nums.length == 0){ return -1 } let left = 0 let right = nums.length-1
while(left < right){ let mid = Math.ceil(left + (right-left)/2) if(nums[mid] == target){ left = mid } else if(nums[mid] < target){ left = mid + 1 } else if(nums[mid] > target){ right = mid - 1 } } if(nums[right] == target){ return right }else{ return -1 } }
|
解答题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
var searchRange = function(nums, target) { let left = searchLeftTarget(nums,target) if(left !== -1){ let right = searchRightTarget(nums,target) return [left,right] }else{ return [-1,-1] } };
|
动图随便看看
二分查找target

searchLeftTarget
