leetcode--查找

二分

4. 寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
方法一:暴力解法:合并以、排序、得到中位数(分析和代码省略)
复杂度分析:

时间复杂度:O((M + N) \log (M + N))O((M+N)log(M+N)),这里 MM 和 NN 分别是两个数组的长度。
空间复杂度:O(M + N)O(M+N)。
方法二:实现归并排序、得到中位数(分析和代码省略)
复杂度分析:

时间复杂度:O(M + N)O(M+N),这里 MM 和 NN 分别是两个数组的长度,代码只看了数组长度之和的一半,常数系数视为 11。
空间复杂度:O(1)O(1),我们没有借助其它的空间,使用到的临时变量也只有常数个。
方法三:二分查找

  1. 只有一个有序数组的时候中位数的性质

29. 两数相除 :
二分 + 倍增乘法解法(含模板)

def divide(self, dividend: int, divisor: int) -> int:
        # 将被除数和除数转化为正数
        sign = 1
        if divisor * dividend < 0:  # 如果符号不同,则结果返回要变成负数
            sign = -1
            divisor = abs(divisor)
            dividend = abs(dividend)

        elif divisor < 0 and dividend < 0: # 如果被除数和除数都是负值,结果不修改符号
            divisor = abs(divisor)
            dividend = abs(dividend)

        remain = dividend  # 余数
        result = 0  # 商
        while remain >= divisor: 
            cur = 1 # 倍增商
            div = divisor # 倍增值
            while div + div < remain:
                cur += cur 
                div += div 
            remain -= div  # 余数递减
            result += cur  # 商值累计
        
        if sign==-1:  
            result = -result
        
        if result>=2**31:  # 按照题目要求,溢出处理
            result = 2**31-1

        return result

278. 第一个错误的版本 : 使用交互函数充当 check 进行二分
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例:
给定 n = 5,并且 version = 4 是第一个错误的版本。
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。

def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        left, right = 1, n
        while left < right:
            mid = (left + right) // 2
            if isBadVersion(mid):
                right = mid
            else:
                left = mid + 1
        return left

374. 猜数字大小 : 使用交互函数充当 check 进行二分
猜数字游戏的规则如下:
每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
-1:我选出的数字比你猜的数字小 pick < num
1:我选出的数字比你猜的数字大 pick > num
0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字

852. 山脉数组的峰顶索引 :
二分 & 三分查值问题
山脉数组的峰顶索引
符合下列属性的数组 arr 称为 山脉数组 :arr.length >= 3
存在 i(0 < i < arr.length - 1)使得:arr[0] < arr[1] < … arr[i-1] < arr[i]
arr[i] > arr[i+1] > … > arr[arr.length - 1]
给你由整数组成的山脉数组 arr ,返回任何满足 arr[0] < arr[1] < … arr[i - 1] < arr[i] > arr[i + 1] > … > arr[arr.length - 1] 的下标 i 。
二分本质 & 恢复二段性处理

33. 搜索旋转排序数组
(找目标值) : 严格 O(logN),一起看清二分的本质
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

81.搜索旋转排序数组 II
(找目标值) : 详解为何元素相同会导致 O(n),一起看清二分的本质
已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。

153. 寻找旋转排序数组中的最小值(找最小值) : 严格 O(logN),一起看清二分的本质
153. 寻找旋转排序数组中的最小值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

154. 寻找旋转排序数组中的最小值 II
找最小值) : 详解为何元素相同会导致 O(n),一起看清二分的本质
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

34. 在排序数组中查找元素的第一个和最后一个位置
考察对「二分」的理解,以及 check 函数的「大于 小于」怎么写
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值