二分查找

正常实现

题解

  1. public int binarySearch(int[] nums, int key) {
  2. int l = 0, h = nums.length - 1;
  3. while (l <= h) {
  4. int m = l + (h - l) / 2;
  5. if (nums[m] == key) {
  6. return m;
  7. } else if (nums[m] > key) {
  8. h = m - 1;
  9. } else {
  10. l = m + 1;
  11. }
  12. }
  13. return -1;
  14. }

二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度为 O(logN)。

有两种计算中值 m 的方式:

  • m = (l + h) / 2
  • m = l + (h - l) / 2

l + h 可能出现加法溢出,也就是说加法的结果大于整型能够表示的范围。但是 l 和 h 都为正数,因此 h - l 不会出现加法溢出问题。所以,最好使用第二种计算法方法。

我感觉这里l,h最终都会扫到一个点上,即某一时刻l=h=m,只有L=h时,m才会=l=h,所以循环终止条件为l<=h

744 寻找比目标字母大的最小字母

题目描述

给定一个只包含小写字母的有序数组letters和一个目标字母target,寻找有序数组里面比目标字母大的最小字母。

数组里字母的顺序是循环的。举个例子,如果目标字母target = 'z' 并且有序数组为letters = ['a', 'b'],则答案返回'a'。

示例

  1. 输入:
  2. letters = ["c", "f", "j"]
  3. target = "a"
  4. 输出: "c"
  5. 输入:
  6. letters = ["c", "f", "j"]
  7. target = "c"
  8. 输出: "f"
  9. 输入:
  10. letters = ["c", "f", "j"]
  11. target = "d"
  12. 输出: "f"
  13. 输入:
  14. letters = ["c", "f", "j"]
  15. target = "g"
  16. 输出: "j"
  17. 输入:
  18. letters = ["c", "f", "j"]
  19. target = "j"
  20. 输出: "c"
  21. 输入:
  22. letters = ["c", "f", "j"]
  23. target = "k"
  24. 输出: "c"

题解

  1. class Solution:
  2. def nextGreatestLetter(self, letters: List[str], target: str) -> str:
  3. l,r = 0,len(letters)-1
  4. if target<letters[l] or target>=letters[r]:
  5. return letters[l]
  6. while l<=r:
  7. m = l + (r-l)//2
  8. if target>=letters[m]:
  9. l = m + 1
  10. else:
  11. r = m - 1
  12. return letters[l]

这里l<=r,不能l<r,例如

  1. 输入:
  2. ["c","f","j"]
  3. "c"
  4. 输出:
  5. "c"
  6. 预期:
  7. "f"

因为target < letters[m]时,r=m-1会出现r指到l的情况,这时还需一次循环。

我的思路时将所有情况分为三种:

  • target<letters[l]
  • target>=letters[r]
  • letters[l]<=target<letters[r]

因为1,2种结果一样就归为一类,上面代码主要讨论第三种。

最终l是要比m前一位,所以输出l

278第一个错误的版本

题目描述

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例

  1. 给定 n = 5,并且 version = 4 是第一个错误的版本。
  2. 调用 isBadVersion(3) -> false
  3. 调用 isBadVersion(5) -> true
  4. 调用 isBadVersion(4) -> true
  5. 所以,4 是第一个错误的版本。 

题解(python)

  1. # The isBadVersion API is already defined for you.
  2. # @param version, an integer
  3. # @return a bool
  4. # def isBadVersion(version):
  5. class Solution:
  6. def firstBadVersion(self, n):
  7. """
  8. :type n: int
  9. :rtype: int
  10. """
  11. l,r = 1,n
  12. while l<=r:
  13. m = l+(r-l)//2
  14. if isBadVersion(m):
  15. r = m-1
  16. else:
  17. l = m+1
  18. return l

总结

做了这么几道题,有点感觉。例如上面这道,或者之前的最终情况我们可以想象成三个元素的区间,[a(0),a(1),a(2)],l=0,r=2。讨论一下第一轮m=1时,a(1)是否符合条件,就容易判断边界条件了。

我感觉当l<=r时,也就是考虑l=r时,也就是最后肯定会出现l=r,这时候上面这个例子中,m=l=r, 此时若m处是满足条件的,那么r=m-1,r就是最后错误版本之前正确的版本,l=m最后错误版本。若m处不满足条件,那么l=m+1,l就是最后错误版本,此时m=r是最后正确版本。

也就是说,当l<=r时,这种情况下l如果等于m-1,那么l最后会指向最后满足,我们设定条件的位置,这道题的条件即是否是错误版本,r则会指向其之前一位。

leetcode刷题-- 3.二分查找的更多相关文章

  1. LeetCode刷题总结-二分查找和贪心法篇

    本文介绍LeetCode上有关二分查找和贪心法的算法题,推荐刷题总数为16道.具体考点归纳如下: 一.二分查找 1.数学问题 题号:29. 两数相除,难度中等 题号:668. 乘法表中第k小的数,难度 ...

  2. C#LeetCode刷题-二分查找​​​​​​​

    二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...

  3. LeetCode刷题专栏第一篇--思维导图&时间安排

    昨天是元宵节,过完元宵节相当于这个年正式过完了.不知道大家有没有投入继续投入紧张的学习工作中.年前我想开一个Leetcode刷题专栏,于是发了一个投票想了解大家的需求征集意见.投票于2019年2月1日 ...

  4. LeetCode刷题总结之双指针法

    Leetcode刷题总结 目前已经刷了50道题,从零开始刷题学到了很多精妙的解法和深刻的思想,因此想按方法对写过的题做一个总结 双指针法 双指针法有时也叫快慢指针,在数组里是用两个整型值代表下标,在链 ...

  5. LeetCode刷题总结-数组篇(上)

    数组是算法中最常用的一种数据结构,也是面试中最常考的考点.在LeetCode题库中,标记为数组类型的习题到目前为止,已累计到了202题.然而,这202道习题并不是每道题只标记为数组一个考点,大部分习题 ...

  6. LeetCode刷题总结-数组篇(中)

    本文接着上一篇文章<LeetCode刷题总结-数组篇(上)>,继续讲第二个常考问题:矩阵问题. 矩阵也可以称为二维数组.在LeetCode相关习题中,作者总结发现主要考点有:矩阵元素的遍历 ...

  7. LeetCode刷题总结-树篇(上)

          引子:刷题的过程可能是枯燥的,但程序员们的日常确不乏趣味.分享一则LeetCode上名为<打家劫舍 |||>题目的评论: 如有兴趣可以从此题为起点,去LeetCode开启刷题之 ...

  8. LeetCode刷题笔记和想法(C++)

    主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...

  9. LeetCode刷题的一点个人建议和心得

    目录 1.    为什么我们要刷LeetCode? 2.    LeetCode的现状和问题 3.    本文的初衷 4.    LeetCode刷题建议 4.1入门数据结构,打基础阶段 4.2 建立 ...

随机推荐

  1. Jmeter_请求原件之参数化CSV

    1.用途:注册10个账户 2.用CSV 制造数据相对比TEXT更方便 3.创建CSV 文件,注册账户和密码如下 4.Jmeter设置如下 因为是注册10个账户,要运行10次 5.线程组->添加- ...

  2. Maven (一)--- 入门和依赖

    部分图片来自参考资料 问题 : - maven 生命周期是怎么样的 - mvn clean install 与 mvn clean deploy 的区别是什么 概述 Maven 是一种构建项目的工具, ...

  3. 【PAT甲级】1093 Count PAT's (25 分)

    题意: 输入一行由大写字母'P','A','T',组成的字符串,输出一共有多少个三元组"PAT"(相对顺序为PAT即可),答案对1e9+7取模. AAAAAccepted code ...

  4. Node.js 服务端处理图片

    Node 服务端处理图片 服务端进行图片处理是很常见的需求,但是Node在这一块相对来说比较薄弱.找了几个比较常见的模块来解决问题. gm GraphicsMagick for node 使用Open ...

  5. 【代码学习】PYTHON 列表循环遍历及列表常见操作

    一.for循环 为了更有效率的输出列表的每个数据,可以使用循环来完成 代码: A = ['xiaoWang','xiaoZhang','xiaoHua'] for tempName in A: pri ...

  6. Jmeter和nmon shell命令

    jmeter: sh jmeter -n -t /data/LPPZ/scripts/oauth.jmx -l /data/LPPZ/log/log.jtl nmon: ./nmon_linux_x8 ...

  7. ORM框架的概述

    ORM: object relation mapping [对象][关系]映射    将对象  映射到  数据库中        类名        数据库表名        对象           ...

  8. 精简DOCKER环境

    docker system prune -a WARNING! This will remove:  - all stopped containers  - all networks not used ...

  9. tkinter的listbox、radiobutton和checkbutton学习(2)

    1.tkinter的listbox 1.1 代码 #第1步,导出模块 import tkinter as tk #定义窗口,及其标题.大小和位置 win = tk.Tk() win.title('Li ...

  10. !important面试汇总啊

    https://www.jianshu.com/p/feab89b88d6b https://juejin.im/post/5c64d15d6fb9a049d37f9c20#heading-57