力扣算法题笔记——二分法

三,搜索插入位置(35)

题目:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例1:输入: [1,3,5,6], 5  输出: 2
示例 2: 输入: [1,3,5,6], 2  输出: 1
示例 3: 输入: [1,3,5,6], 7  输出: 4
思路:先查找数组中是否有目标数字,如果存在,则首先与最大值和最小值作对比,然后再用穷搜法查找位置。如果数字不在数组中,则同样用穷搜法找到对应的位置,本来我想用二分法来找的,但是写了很久没有写出二分法的算法
后来改进,先判断数字是否是应该位于数组的首位,如果不是再进行穷搜

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        n=len(nums)
        if target>=nums[-1]:#比所有的数字都小
            return n if target>nums[-1] else n-1
        elif target<=nums[0]:#比所有数字都大
            return 0        
        else:#目标值不在数组中
            for i in range(n):
                if nums[i]>=target:
                    return i          

后来又用了二分法,能够减少时间复杂度,但是只能借助辅助函数,暂时没把两者合二为一

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        n=len(nums)
        if target>=nums[-1]:#比所有的数字都小
            return n if target>nums[-1] else n-1
        elif target<=nums[0]:#比所有数字都大
            return 0        
        else:#目标值不在数组中
            return self.bin_search(nums,target,0,len(nums))
    def bin_search(self,nums,target,left,right):
        med=(left+right)//2
        while left<right:
            if target<nums[med]:
                return self.bin_search(nums,target,left,med)
            elif nums[med]<=target<=nums[med+1]:
                return med if target==nums[med] else med+1
            else:
                return self.bin_search(nums,target,med,right)      

69.x的平方根

题目:实现 int sqrt(int x) 函数。  计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:  输入: 4  输出: 2
示例 2:  输入: 8  输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去
思路:
  对0和1特殊处理,返回本身,其他数值的平方根的整数部分一定不小于1,因此坐指针从1开始,右指针从自身开始,终止条件是左指针比右指针小一,原因:,右指针比左指针大1,说明此时计算的结果在两个相邻的数值之间对比看,由于我们要的结果是整数部分而不是平方分的四舍五入后的结果,因此,结果一定是那个小的数值。

class Solution:
    def mySqrt(self, x: int) -> int:
        if x<=1:
            return x
        left=1
        right=x
        while right-left>1:
            mid=left+math.ceil((right-left)/2)#取两者的右中位数,参考了别人的思维
            tmp=mid**2
            if tmp==x:
                return mid
            elif tmp>x:
                right=mid
            else:
                left=mid
        return left        

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

二分法:采用每次缩小一半搜索范围的思想,从右中位数开始搜索,如果目标值大于右中位数,则左指针增加,如果目标值小于右中位数,则右指针减小。如果两者相等,则结束搜索。循环直到右指针大于左指针,此时说明目标值不在范围内。
注意,左指针和右指针在改变时不能等于中位数,否则会陷入无限循环。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        n=len(nums)
        left=0 #左指针
        right=len(nums)-1# 右指针
        while left<=right:
            mid=math.ceil((left+right)/2)
            if nums[mid]==target:
                return mid
            elif nums[mid]<target:
                left=mid+1
            else:
                right=mid-1
        return -1        

167、两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:返回的下标值(index1 和 index2)不是从零开始的;  你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:  输入: numbers = [2, 7, 11, 15], target = 9  输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

双指针法:一前一后的两个指针。分别从头尾搜索,当两数之和大于目标值,则让右指针向前,反之,让左指针向右。

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        nums=numbers
        l=0
        r=len(nums)-1
        res=[]
        while l<r:
            if nums[l]+nums[r]==target:
                return [l+1,r+1]
            elif nums[l]+nums[r]>target:
                r-=1
            else:
                l+=1        

367、有效地完全平方数

给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
说明:不要使用任何内置的库函数,如 sqrt。
示例 1:
输入:16  输出:True 
示例 2:
输入:14  输出:False
二分法:
  1和0这两个数可以特殊处理,其他的数的平方根均不大于其值的一半,数字越大越是这样。因此,采用二分法,每次缩小一半的搜索范围。

class Solution:
    def isPerfectSquare(self, num: int) -> bool:
        if num<=1:
            return True
        l=1
        r=num
        while l<=r:
            mid=(l+r)//2
            if mid**2==num:
                return True
            elif mid**2>num:
                r=mid-1
            else:
                l=mid+1
        return False        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值