持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
LeetCode 75 —— 704. 二分查找
一、题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。 n 将在 [1, 10000]之间。 nums 的每个元素都将在 [-9999, 9999]之间。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/bi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
二分查找应该是最常用的算法之一,思路很简单,设置一个left和right,初始值left设置为0,right设置为数组长度减一。因为数组内元素是升序排列的,所以我们取数组中间元素的索引mid,然后将其指向的元素与目标值进行比较,如果该元素大于目标值,则将left的值设置为mid,如果该元素小于目标值,我们就将right的值设置为mid。直到mid指向的值等于目标值。
func search(nums []int, target int) int { var left,right,mid int left = 0 right = len(nums)-1 mid = (right - left) / 2 + left for nums[mid] != target{ if((left + 1 == right || left == right) && (nums[left] != target && nums[right] != target) ){ return -1 } fmt.Println(left,right,mid) if( nums[mid] < target ) { left = mid }else { right = mid } mid = (right - left) / 2.0 + left } return mid } 结果这种解法总是有部分测试用例过不去。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是一次通过,刚开始的第一想法是上面那种思路,但是有个问题,因为如果用nums[mid]与target进行判断,就会出现不知道什么时候退出的情况。因此不能使用上面那种思路。
而应该是判断left是否大于right,因为当nums[mid] > target时,right = mid - 1,而
nums[mid] < target时,left = mid + 1。因为mid = (right - left) / 2 + left,如果right比left大1,而直接给left或right赋值为mid的话,就会出现mid还是等于left,可能会导致原地踏步。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。
(版本二)左闭右开区间:
func search(nums []int, target int) int { high := len(nums) low := 0 for low < high { mid := low + (high-low)/2 if nums[mid] == target { return mid } else if nums[mid] > target { high = mid } else { low = mid+1 } } return -1 } 作者:carlsun-2 链接:https://leetcode.cn/problems/binary-search/solution/704-er-fen-cha-zhao-er-fen-fa-zhong-xun-l74cr/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、AC 代码:
func search(nums []int, target int) int {
var left,right,mid int
left = 0
right = len(nums)-1
for left <= right {
mid = (right - left) / 2 + left
if(nums[mid] == target){
return mid
}else if(nums[mid] > target){
right = mid - 1
}else if nums[mid] < target{
left = mid + 1
}
}
return -1
}
四、总结:
二分查找的时间复杂度为O(log n),空间复杂度为O(1)。
下面上labuladong大佬的绝活:
模板来源:
作者:掘金酱
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。