数组:力扣二分法题目

这篇博客介绍了如何利用二分查找和牛顿迭代法解决编程问题,包括在排序数组中查找元素范围、搜索插入位置、求平方根以及判断完全平方数的有效性。通过优化算法,实现了O(logx)的时间复杂度,节省了计算资源。同时,文章还对比了两种方法在不同场景下的优势和适用性。
摘要由CSDN通过智能技术生成


教程:https://github.com/youngyangyang04/leetcode-master

二分法

  • 时间复杂度:O(logx),即为二分查找需要的次数。
  • 空间复杂度:O(1)。

牛顿迭代法

  • 时间复杂度:O(log x),此方法是二次收敛的,相较于二分查找更快。
  • 空间复杂度:O(1)。
  • 公式:(x+a/x)/2。(遇到平方根都可以考虑牛顿迭代法

34.在排序数组中查找元素的第一个和最后一个位置(中等)

链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

题目描述:给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。

进阶
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
在这里插入图片描述

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if(len(nums)==0):
            return [-1,-1]
        l , r = 0, len(nums)-1
        left = right = -1
        while(l <= r):
            m = l + (r - l) // 2
            if(nums[m] == target):
                left = right = m
                break
            if(nums[m] < target):
                l = m + 1
            if(nums[m] > target):
                r = m - 1
        if(left != -1):
            while(m - 1 >= 0 and nums[m-1] == target):
                m = m - 1  
                left = m                               
            while(m + 1 < len(nums) and nums[m+1] == target):
                m = m + 1  
                right = m 
        return [left,right]

思路:二分查找,查到一个,往左右两边用while去寻找是否有更小更大的值。
官方解:定义一个boolen值的lower,定义一个函数,将list和target传进去算leftIndex 和 rightIndex。
注意:考虑边界问题(l > 0 and r < length)。

35.搜索插入位置(简单)

链接:https://leetcode-cn.com/problems/search-insert-position/
题目描述:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。
在这里插入图片描述
解法:就是普通的二分查找法。由于 >= 时,只移动right,当 middle == target 时,right在下一轮移动到 < lefr,left 不变,所以最后返回 left 即可。(使用这种方法就不用判断边界,边界判断不恰当反而会报错)

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        l , r = 0 , len(nums)-1      
        while(l<=r):
            mid=l+(r-l)//2
            if(nums[mid]<target):
                l=mid+1
            else:
                 r=mid-1       
        return l      

注意

  • nums数组与target比较时用 nums[m] == target
  • left, right加减middle
  • 插入第一个元素的时候,判断 right<0 而不是 right<=0 (不需要判断边界问题)

复杂度分析

  • 时间复杂度:O(logx),即为二分查找需要的次数。
  • 空间复杂度:O(1)。

69.x的平方根(简单)

链接:https://leetcode-cn.com/problems/sqrtx/solution/niu-dun-die-dai-fa-by-loafer/
解法1:普通的二分查找法,由于根取整数,找到比middle小的那一个即可。由于结束条件是left > right, 所以最后一轮迭代时,right即我们要求的值。
解法2:牛顿迭代法。(x+a/x)/2。(遇到平方根都可以考虑牛顿迭代法
在这里插入图片描述

#二分法
class Solution:
    def mySqrt(self, x: int) -> int:
        left,right = 1,x
        while(left <= right):
            mid = left + (right - left) // 2
            if(mid * mid <= x):
                left = mid + 1
            if(mid * mid == x):
                return mid
            if(mid * mid > x):    #不要偷懒用else(报错!!!)
                right = mid - 1
        return (right)
#牛顿迭代法
class Solution:
    def mySqrt(self, x: int) -> int:
        if x == 0:
            return 0
        
        C, x0 = float(x), float(x)
        while True:
            xi = 0.5 * (x0 + C / x0)
            if abs(x0 - xi) < 1e-7:
                break
            x0 = xi
        
        return int(x0)

复杂度分析

  • 时间复杂度:O(log x),此方法是二次收敛的,相较于二分查找更快。
  • 空间复杂度:O(1)。

367.有效的完全平方数(简单)

链接:https://leetcode-cn.com/problems/valid-perfect-square/
在这里插入图片描述
解法1:普通的二分法。用了2种方法实现(全闭,左开右闭)
解法2:牛顿迭代法
在这里插入图片描述

#左闭右开
class Solution:
    def isPerfectSquare(self, num: int) -> bool:
        if(num<2):
            return True
        left = 2
        right = num // 2 + 1
        while left < right:
            x =  ( right + left) // 2
            if(x*x == num):
                return True
            elif(x*x < num):
                left = x + 1 
            else:
                right = x 
        return False
# 迭代法
class Solution:
    def isPerfectSquare(self, num: int) -> bool:
        if num < 2:
            return True   
        x = num // 2
        while x * x > num:
            x = (x + num // x) // 2
        return x * x == num

704.二分查找(简单)

链接:https://leetcode-cn.com/problems/binary-search/
题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
在这里插入图片描述
思路:最简单的二分法。

# JS实现的
var search = function(nums, target) {
    let l = 0, r = nums.length - 1;
    while(l <= r){
        let m = (r+l) >> 1;
        if(target === nums[m]){
            return m;
        }
        else if (target < nums[m]){
            r = m - 1;
        }
        else{
            l = m + 1;
        }
    }
    return -1;
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值