二分查找

正常实现

题解

public int binarySearch(int[] nums, int key) {
int l = 0, h = nums.length - 1;
while (l <= h) {
int m = l + (h - l) / 2;
if (nums[m] == key) {
return m;
} else if (nums[m] > key) {
h = m - 1;
} else {
l = m + 1;
}
}
return -1;
}

二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度为 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'。

示例

输入:
letters = ["c", "f", "j"]
target = "a"
输出: "c" 输入:
letters = ["c", "f", "j"]
target = "c"
输出: "f" 输入:
letters = ["c", "f", "j"]
target = "d"
输出: "f" 输入:
letters = ["c", "f", "j"]
target = "g"
输出: "j" 输入:
letters = ["c", "f", "j"]
target = "j"
输出: "c" 输入:
letters = ["c", "f", "j"]
target = "k"
输出: "c"

题解

class Solution:
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
l,r = 0,len(letters)-1
if target<letters[l] or target>=letters[r]:
return letters[l]
while l<=r:
m = l + (r-l)//2
if target>=letters[m]:
l = m + 1
else:
r = m - 1
return letters[l]

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

输入:
["c","f","j"]
"c"
输出:
"c"
预期:
"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 的次数。

示例

给定 n = 5,并且 version = 4 是第一个错误的版本。

调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true 所以,4 是第一个错误的版本。 

题解(python)

# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version): class Solution:
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
l,r = 1,n while l<=r:
m = l+(r-l)//2
if isBadVersion(m):
r = m-1
else:
l = m+1
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. 关于 checkbox 的一些操作

    获取checkbox选中的状态 $("#checkbox").is(":checked"); 设置 checkbox 的状态 $("#checkbox ...

  2. maplotlib python 玩具绘图 横向纵向条状图

    from matplotlib import font_manager#解决zh-han图形汉字乱码 my_font = font_manager.FontProperties(fname=" ...

  3. MongoDB - 运行

    运行 mongod --dbpath (mongod is the "Mongo Daemon") 在shell用mongo或者用studio 3t可视化连接 创建用户 db.cr ...

  4. C#中equals和==的区别有哪些

    本文导读:C# 中==是用来判断变量的值是否相等,相等返回true,不相等返回false.Equals是用来判断两个对象(除string类型外)是否相等,相等的 条件是:值,地址,引用全相等,因为St ...

  5. input输入框type设置为number,maxlength无效

    一个小细节,以前很少注意,直到最近做的一个项目,当我把一个输入数字的input框的类型设置为number时,input框还是可以无限输入,设置maxlengh=10就不起作用了.然后我就去百度了一下, ...

  6. 《Web安全攻防 渗透测试实战指南》 学习笔记 (二)

    Web安全攻防 渗透测试实战指南   学习笔记 (二)   第二章  漏洞环境及实践  

  7. vmware虚拟机linux添加硬盘后先分区再格式化操作方法

    先在虚拟机里填加硬盘,如图. 进入linux后台,df-l ,没有显示sdc盘,更切换的是,在fdisk中,却有sdc 看fdisk -l,确实有sdc. 说明sdc还没有分区,也没有格式化,也没有挂 ...

  8. twisted reactor 实现源码解析

    twisted reactor 实现源码解析 1.      reactor源码解析 1.1.    案例分析代码: from twisted.internet import protocol fro ...

  9. C#多个泛型约束问题

    多个约束之间使用逗号隔开,但不重复T约束. 1. private void AddControl<T>(TabPage tabPage, T userControl) where T: U ...

  10. 吴裕雄--天生自然TensorFlow2教程:多输出感知机及其梯度

    import tensorflow as tf x = tf.random.normal([2, 4]) w = tf.random.normal([4, 3]) b = tf.zeros([3]) ...