二分查找方法 leetcode题

2023-05-16

这里用来 记录 使用二分查找方法 的题目

1. 704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间

解法1:  二分查找必须注重细节:(1): <= or < (2): + 1 or -1

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        while left <= right: # 查找的区间为闭区间,所以要等号,保证数据都被查找过, 小于等于结束条件: left=end+1, 
            # mid = left + (right-left) // 2 # 和 mid = (left+right)//2  一样
            mid = (left+right) // 2 
            if nums[mid] == target:
                break
            elif nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1  # 验证过mid 所以可以 +1或-1
        # 加补丁
        return mid if nums[mid] == target else -1

解法2:  不加补丁

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        while left <= right: # 查找的区间为闭区间,所以要等号,保证数据都被查找过, 小于等于结束条件: left=end+1, 
            # mid = left + (right-left) // 2 # 和 mid = (left+right)//2  一样
            mid = (left+right) // 2 
            if nums[mid] == target:
                return mid  # 找到就返回
            elif nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1  # 验证过mid 所以可以 +1或-1
        return -1

 

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

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [], target = 0
输出:[-1,-1]

解法1: 二分查找, 分别找 最左侧,和右侧的

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if not nums:
            return [-1, -1]
        def binarySearch_left(nums, target): # 找最左侧的
            left = 0
            right = len(nums) - 1
            ans = -1 # 多使用一个变量
            while left <= right:
                mid = left + (right - left) // 2
                # 找左边的
                if nums[mid] == target:
                    ans = mid
                    right = mid - 1 # 继续往左找, 已经记录下了找到过的位置,不怕丢
                elif nums[mid] < target:
                    left = mid + 1
                elif nums[mid] > target:
                    right = mid - 1
            return ans if 0<=ans <len(nums) and nums[ans]==target else -1
        left = binarySearch_left(nums, target)   

        def binarySearch_right(nums, target):  #  找最右侧的
            left = 0
            right = len(nums) - 1
            ans = -1 # 用来记录 
            while left <= right:
                mid = left + (right - left) // 2
                if nums[mid] < target:  # 换成 常规写法
                    left = mid + 1
                elif nums[mid] == target:  # 只能找到 相等
                    ans = mid    # 这种思路,简单容易想, 并且和常规二分相同, 可以用
                    left = mid + 1  # 相等了, 继续 left 右移动, 来 判断右边还有没有
                elif nums[mid] > target:
                    right = mid - 1 
            # ans 可能没找到 
            return ans if 0 <= ans < len(nums) and nums[ans]==target else -1
        right = binarySearch_right(nums, target)
        return [left, right]
                

3. 面试题 10.03. 搜索旋转数组

33. 搜索旋转排序数组

搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。

示例1:

 输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
 输出: 8(元素5在该数组中的索引)

示例2:

 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 11
 输出:-1 (没有找到)

提示:

  1. arr 长度范围在[1, 1000000]之间

解法1: 遍历O(n)

解法2: 二分查找, (面试遇到这个题,没搞出 😣)

class Solution:
    def search(self, arr: List[int], target: int) -> int:
        # 比较  注意细节
        left = 0
        right = len(arr) - 1
        while left < right:  # 若使用 <=:  最后需加判断条件:0 <= left < len(arr)
            mid = (left + right) // 2
            # 注意比较的条件: 是比较 arr[left] 和 arr[mid] 而不是 left和mid
            if arr[left] < arr[mid]:  # 左边是升序
                if arr[left] <= target <= arr[mid]: # target在左边
                    right = mid  # 不是mid-1
                else:  # target在右边
                    left = mid + 1
            elif arr[left] > arr[mid]: # 左边不是升序
                if arr[left] <= target or target <= arr[mid]: # 值在左边
                    right = mid
                else:  # target在右边
                    left = mid + 1
            else: # 即 arr[left] == arr[mid]
                if arr[left] == target:
                    # 找到 索引最小的了
                    break
                else:
                    left += 1  # left+1 从左逐个比较 
        # print(left)
        # if arr[left] == target:  # if else 
        #     return left
        # return -1
        return left if arr[left] == target else -1

4. 668. 乘法表中第k小的数

几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k小的数字吗?

给定高度m 、宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第k 小的数字。

例 1:

输入: m = 3, n = 3, k = 5
输出: 3
解释: 
乘法表:
1	2	3
2	4	6
3	6	9

第5小的数字是 3 (1, 2, 2, 3, 3).

例 2:

输入: m = 2, n = 3, k = 6
输出: 6
解释: 
乘法表:
1	2	3
2	4	6

第6小的数字是 6 (1, 2, 2, 3, 4, 6).

注意:

  1. m 和 n 的范围在 [1, 30000] 之间。
  2. k 的范围在 [1, m * n] 之间。

解法1: 二分查找  (O(n*n)超时)

class Solution:
    def findKthNumber(self, m: int, n: int, k: int) -> int:
        # 1. 先生成 乘法表,O(n*n) 超时
        # 乘法表 有个特性: mxn 为乘法表中的 最大值,乘法表取值范围[1, m*n], 同时 共有 m*n个数
        # 在 [1, m*n] 使用二分查找, mid为 中值, 求的 小于mid的值个数为x,若 x <k,则第k小数 在 (mid, m*n]之间,否则在 [0, mid]之间;
        def search(m, n, mid):
            count = 0
            # 遍历每一行 共 m行
            for i in range(1, m+1):  # 得到每行中 小于等于mid的 数字个数;
                count += min(mid//i, n)  
            return count

        left = 1
        right = m*n
        while left < right: # 为什么不带等号呢?
            mid = (left + right) // 2
            if search(m, n, mid) < k:  # 怎么求解 小于mid的数有多少呢?
                left = mid + 1
            else:
                right = mid # 有等于k的情况所以不 -1
        return left

5. 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二分查找方法 leetcode题 的相关文章

随机推荐

  • idea中java版本设置

    1 打开file gt Project structure gt project Settings gt Project gt Project SDK中设置 2 设置IDEA本身的jdk版本 打开file gt settings gt ja
  • 剑指 Offer 59 - II. 队列的最大值

    剑指 Offer 59 II 队列的最大值 请定义一个队列并实现函数 max value 得到队列里的最大值 xff0c 要求函数max value push back 和 pop front 的均摊时间复杂度都是O 1 若队列为空 xff
  • 剑指 Offer 46. 把数字翻译成字符串

    剑指 Offer 46 把数字翻译成字符串 给定一个数字 xff0c 我们按照如下规则把它翻译为字符串 xff1a 0 翻译成 a xff0c 1 翻译成 b xff0c xff0c 11 翻译成 l xff0c xff0c 25 翻译成
  • python 异或的应用

    符号 描述 运算规则 amp 与 两个位都为1时 xff0c 结果才为1 xff08 统计奇数 xff09 全1为1 或 两个位都为0时 xff0c 结果才为0 xff08 统计偶数 xff09 全0为0 异或 两个位相同为0 xff0c
  • day4: 剑指 Offer 64. 求1+2+…+n

    剑指 Offer 64 求1 43 2 43 43 n 求 1 43 2 43 43 n xff0c 要求不能使用乘除法 for while if else switch case等关键字及条件判断语句 xff08 A B C xff09
  • day5: 链表

    1 剑指 Offer 22 链表中倒数第k个节点 输入一个链表 xff0c 输出该链表中倒数第k个节点 为了符合大多数人的习惯 xff0c 本题从1开始计数 xff0c 即链表的尾节点是倒数第1个节点 例如 xff0c 一个链表有6个节点
  • LCP 18. 早餐组合

    小扣在秋日市集选择了一家早餐摊位 xff0c 一维整型数组 staple 中记录了每种主食的价格 xff0c 一维整型数组 drinks 中记录了每种饮料的价格 小扣的计划选择一份主食和一款饮料 xff0c 且花费不超过 x 元 请返回小扣
  • 第 208 场周赛

    1 5523 文件夹操作日志搜集器 class Solution def minOperations self logs List str gt int 栈 xff0c 先进 后出 zhan 61 39 main 39 for log in
  • day 5: 字符串

    1 剑指 Offer 38 字符串的排列 输入一个字符串 xff0c 打印出该字符串中字符的所有排列 你可以以任意顺序返回这个字符串数组 xff0c 但里面不能有重复元素 示例 xff1a 输入 xff1a s 61 34 abc 34 输
  • day6: 数组

    1 18 四数之和 给定一个包含 n 个整数的数组 nums 和一个目标值 target xff0c 判断 nums 中是否存在四个元素 a xff0c b xff0c c 和 d xff0c 使得 a 43 b 43 c 43 d 的值与
  • day7: 剑指 Offer 44. 数字序列中某一位的数字

    1 剑指 Offer 44 数字序列中某一位的数字 数字以0123456789101112131415 的格式序列化到一个字符序列中 在这个序列中 xff0c 第5位 xff08 从下标0开始计数 xff09 是5 xff0c 第13位是1
  • casbin 使用说明记录

    本文简单记录casbin 安装步骤 使用 Casbin 作为 ThinkPHP 的权限控制中间件 PHP Casbin 是一个强大的 高效的开源访问控制框架 xff0c 它支持基于各种访问控制模型的权限管理 Think Casbin 是一个
  • 844. 比较含退格的字符串

    给定 S 和 T 两个字符串 xff0c 当它们分别被输入到空白的文本编辑器后 xff0c 判断二者是否相等 xff0c 并返回结果 代表退格字符 注意 xff1a 如果对空文本输入退格字符 xff0c 文本继续为空 示例 1 xff1a
  • 笔试题记录

    1 逆波兰表达式 是称为 后缀表达式 xff0c 把运算量写在前面 xff0c 把算符写在后面 写出a b c d 43 e f g h 43 i j k 的逆波兰表达式 拆开写各个部分的 xff1a 按优先级 xff08 1 xff09
  • 牛客网 赛码在线编程中数据读取问题

    一 数据读取的方式 xff08 python3 xff09 1 input 读取输入数据 while True try inputs 61 input except break 2 网站的数据输入是是一个含有多行数据的input文件 in文
  • 贪心算法 leetcode编程题

    1 452 用最少数量的箭引爆气球 在二维空间中有许多球形的气球 对于每个气球 xff0c 提供的输入是水平方向上 xff0c 气球直径的开始和结束坐标 由于它是水平的 xff0c 所以纵坐标并不重要 xff0c 因此只要知道开始和结束的横
  • 排序题 LeetCode题

    1 1370 上升下降字符串 给你一个字符串 s xff0c 请你根据下面的算法重新构造字符串 xff1a 从 s 中选出 最小 的字符 xff0c 将它 接在 结果字符串的后面 从 s 剩余字符中选出 最小 的字符 xff0c 且该字符比
  • BP算法公式推导

    令表示第层的第个神经元到第层的第个神经元的连接权值 xff0c 表示第层第个神经元的输入 xff0c 表示第层第个神经元的输出 xff0c 表示层第个神经元的偏置 xff0c C表示代价函数 则有 xff1a 其中 表示激活函数 训练多层网
  • 卷积神经网络中的Separable Convolution_转载

    卷积神经网络在图像处理中的地位已然毋庸置疑 卷积运算具备强大的特征提取能力 相比全连接又消耗更少的参数 xff0c 应用在图像这样的二维结构数据中有着先天优势 然而受限于目前移动端设备硬件条件 xff0c 显著降低神经网络的运算量依旧是网络
  • 二分查找方法 leetcode题

    这里用来 记录 使用二分查找方法 的题目 1 704 二分查找 给定一个 n 个元素有序的 xff08 升序 xff09 整型数组 nums 和一个目标值 target xff0c 写一个函数搜索 nums 中的 target xff0c