leetcode刷题小记2023.1.29
二分查找类题目
704. 二分查找
问题: 一开始用了顺序查找提交也没问题,可能是测试用例过于简单且时间复杂度高。
使用二分查找的题目:顺序数组&元素不重复
疑惑点: 为什么middle=left +(right-left)/2 会防止溢出,我使用的是middle= (left+right)/2
35.搜索插入位置
问题: 一开始没有想清楚会出现几种情况,只考虑了找到,以及插入在数组中的情况,导致二分查找边界报错。
思路: 先想清楚分几种情况,
一、目标插入在数组前 – 会存在left>right(0,-1)的情况,所以是right+1 =0就ok了
二、目标可以在数组中找到 – 二分查找可解决
三、目标插入在数组中 – right+1 (举例子思考一下,会存在left > right的情况,所以right+1才是当时的情况,其实middle+1也可以,但是left+1了middle也跟着变了,所以用不变的right来表示最合适)
四、目标插入在数组后 --right+1
此外,用暴力破解也很简单,当数组元素>=target时,直接返回下标,这包含了target在数组中,target小于数组,target插入在数组中的情况。唯一缺少的就是,target大于数组,所以再返回一个下标+1,或者返回长度就行了。
public int searchInsert(int[] nums, int target) {
for(int i = 0; i < nums.length;i++){
if(nums[i] >= target){
return i;
}
}
return nums.length;
}
34.在排序数组中查找元素的第一个和最后一个位置
问题: 之前学习的二分法一般用于顺序数组以及数组中没有重复元素的情况,但是本题中元素重复,所以一开始没想出来该如何运用二分法解决。看了眼解析后醒悟可以用二分法来限制一边的边界,然后另一边照搬就ok了。
思路: 第一步还是想清楚分为几种情况,
①数组内无元素(这个提示里给出了,在代码里也要格外限制一下,不然会报错)
②target小于数组中所有的数,target大于数组中所有的数。(这个简单,好实现)
③target在数组的数据范围内,但是数组中没有target。(这个就是把其他情况确定好后的剩余情况,直接返回[-1,-1]就ok了)
④target在数组的数据范围内,数组中有target。(需要额外写函数来找左右边界)
分析: 用二分法来限制单边边界,以寻找左边界举例,middle和target会有三种情况。
middle小于target,说明第一个target在右区间,left=middle+1,right不动,继续寻找。
middle = target,不能确定是否为第一个target,left不动,让right=middle-1继续寻找(我一开始写的right=right-1 保守了,其实middle-1效率更高)
middle大于target,说明最后一个target都在左区间,left不动,right=middle-1寻找第一个target。
在后两个情况下,就可以找到第一个target,当right小于left时,就可以跳出while了,此时的right在target前一位,所以left左边界 = right +1。
寻找右边界同理。
另外,暴力破解很快,但是想尝试二分查找,同时附上暴力破解代码。
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
list1 = []
for i in range(len(nums)):
if nums[i] == target:
list1.append(i)
if len(list1) == 0:
return [-1,-1]
return [list1[0],list1[-1]]
69.x的平方根
问题: 不使用自带函数解决平方根问题,本人采用二分查找的角度进行解决。思考二分查找的特点:顺序数组&&不重复,是可以使用二分查找来找到x的平方根的。
思路: 分情况:
①可以得到整数平方根,也就是存在 x = mm的情况,这种就是直接 x= mm return m就可以了。
②不可以得到整数平方根,需要取较小的那个可以平方的m。
分析: 二分查找,左边界为0,右边界为x/2,平方根肯定小于/2的情况。然后用二分查找选middle,进行情况判断,移动left和right就可以了。
别人的代码: 我是x >mm,x<mm,x=m*m来判断的,但是别人就直接x/m < m,右边界=m。剩余情况(=m和>m直接就左边界=m了,更简单,但是运行起来差不多)
367.有效的完全平方数
问题: 和69差不多一个意思,用二分查找就ok了
思路: 分情况,1单独拿出来就比较好。
分析: 没啥没啥
不是二分的思路:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
if (num**0.5)%1 == 0:
return True
return False