二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。二分查找法的时间复杂度是对数级别的,O(log2n)

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

如果key在array中,返回的是key在array中的位置,如果不在array中,返回的是key应该插入的位置也就是第一个大于key的位置。这里和java.util.Arrays类返回值-(low + 1)不太一样,个人觉得我这种写法做某些算法题更方便。

1. Sqrt(x)

实现 int sqrt(int x) 函数。计算并返回 x 的平方根。x 保证是一个非负整数。

分析:

这道题有两种解法,二分法和拟牛顿法

二分法

class Solution(object):def mySqrt(self, x):""":type x: int:rtype: int"""l = 0r = x // 2 + 1while l <= r:m = (l + r) // 2if m ** 2 <= x and (m + 1) ** 2 > x:return melif m ** 2 > x:r = m - 1else:l = m + 1

牛顿法

class Solution:def mySqrt(self, x):""":type x: int:rtype: int"""r = xwhile r*r > x:r = (r + x//r) // 2return r

2.Search in Rotated Sorted Array I 、II

假设按照升序排序的数组在预先未知的某个关键点上旋转。

(即 0 1 2 4 5 6 7 将变成 4 5 6 7 0 1 2)。

给你一个目标值来搜索,如果数组中存在这个数则返回它的索引,否则返回 -1。

你可以假设数组中不存在重复。

分析:

这是二分查找的一道变形题,因为rotate的缘故,当我们切取一半的时候可能会出现误区,所以我们要做进一步的判断。具体来说,假设数组是A,每次左边缘为l,右边缘为r,还有中间位置是m。在每次迭代中,分三种情况:
(1)如果target==A[m],那么m就是我们要的结果,直接返回;
(2)如果A[m]<A[r],那么说明从m到r一定是有序的(没有受到rotate的影响),那么我们只需要判断target是不是在m到r之间,如果是则把左边缘移到m+1,否则就target在另一半,即把右边缘移到m-1。
(3)如果A[m]>=A[r],那么说明从l到m一定是有序的,同样只需要判断target是否在这个范围内,相应的移动边缘即可。
class Solution(object):def search(self, nums, target):""":type nums: List[int]:type target: int:rtype: int"""l = 0r = len(nums) - 1while l <= r:m = (l + r) // 2if nums[m] == target:return mif nums[m] < nums[r]:if target > nums[m] and target <= nums[r]:l = m + 1else:r = m - 1else:if target < nums[m] and target >= nums[l]:r = m - 1else:l = m + 1return -1

  follow up:

如果数组元素允许重复,怎么办?

这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?

分析:

和Search in Rotated Sorted Array唯一的区别是这道题目中元素会有重复的情况出现。不过正是因为这个条件的出现,出现了比较复杂的case,甚至影响到了算法的时间复杂度。原来我们是依靠中间和边缘元素的大小关系,来判断哪一半是不受rotate影响,仍然有序的。而现在因为重复的出现,如果我们遇到中间和边缘相等的情况,我们就丢失了哪边有序的信息,因为哪边都有可能是有序的结果。假设原数组是{1,2,3,3,3,3,3},那么旋转之后有可能是{3,3,3,3,3,1,2},或者{3,1,2,3,3,3,3},这样的我们判断左边缘和中心的时候都是3,如果我们要寻找1或者2,我们并不知道应该跳向哪一半。解决的办法只能是对边缘移动一步,直到边缘和中间不在相等或者相遇,这就导致了会有不能切去一半的可能。所以最坏情况(比如全部都是一个元素,或者只有一个元素不同于其他元素,而他就在最后一个)就会出现每次移动一步,总共是n步,算法的时间复杂度变成O(n)。代码如下:

class Solution:def search(self, nums, target):""":type nums: List[int]:type target: int:rtype: int"""if not nums:return Falsel = 0r = len(nums) - 1while l <= r:m = (l + r) // 2if nums[m] == target:return Trueif nums[m] < nums[r]:if target > nums[m] and target <= nums[r]:l = m + 1else:r = m - 1elif nums[m] > nums[r]:if target < nums[m] and target >= nums[l]:r = m -1else:l = m + 1else:r -= 1return False

3.Find Minimum in Rotated Sorted Array I 、II

假设一个按照升序排列的有序数组从某未知的位置旋转。

(比如 0 1 2 4 5 6 7 可能变成 4 5 6 7 0 1 2)。

找到其中最小的元素。

你可以假设数组中不存在重复的元素。

分析:

二分法O(log2n):

如果num[m] < num[r],说明pivot也就是最小的元素在m左边,极端情况有可能num[m]就是pivot,所以r = m 而不是 r= m -1,如果num[m] > num[r],则pivot在m的右边,所以l = m + 1

class Solution(object):def findMin(self, nums):""":type nums: List[int]:rtype: int"""l = 0r = len(nums) - 1while l < r:m = (l + r) // 2if nums[m] < nums[r]:r = melse:l = m + 1return nums[l]  

  线性扫描O(n):  

class Solution(object):def findMin(self, nums):""":type nums: List[int]:rtype: int"""for i in range(len(nums) - 1):if nums[i] > nums[i + 1]:return nums[i + 1]return nums[0]

  follow up:

数组中存在重复元素,处理方法与上一道题Search in Rotated Sorted Array一样,对边缘移动一步,直到边缘和中间不在相等或者相遇,这就导致了会有不能切去一半的可能。所以最坏情况(比如全部都是一个元素,或者只有一个元素不同于其他元素,而他就在最后一个)就会出现每次移动一步,总共是n步,算法的时间复杂度变成O(n)

class Solution(object):def findMin(self, nums):""":type nums: List[int]:rtype: int"""l = 0 r = len(nums) - 1while l < r:m = (l + r) // 2if nums[m] < nums[r]:r = melif nums[m] > nums[r]:l = m + 1else:r -= 1return nums[l]

4.Find Peak Element

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组,其中 num[i] ≠ num[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回到任何一个峰值所在位置都可以。

你可以想象得到  num[-1] = num[n] = -∞

例如,在数组 [1, 2, 3, 1]中 3 是峰值元素您的函数应该返回索引号2。

你的解决方案应该是对数复杂度的。

分析:

这道题与Find Minimum in Rotated Sorted Array很像,依然可以用二分法或者线性扫描两种方法解决。

二分法O(log2n):

如果nums[m] > nums[m+1],则说明m的左侧肯定存在峰值,因为如果nums[m-1] < nums[m],则说明m是峰值元素,如果说nums[m -1] > nums[m],则m -1的左侧还存在峰值,如果一直到m = 0的话,那0这个位置的元素就是峰值。

class Solution(object):def findPeakElement(self, nums):""":type nums: List[int]:rtype: int"""l = 0r = len(nums) - 1while l < r:m = (l + r) // 2if nums[m] < nums[m + 1]:l = m + 1else:r = mreturn l

线性扫描O(n):

如果当前元素m比前一元素m-1大的话,则继续向后搜索,如果小的话,说明前一元素m-1即为峰值,因为m-1之前的都比m-1小。

class Solution(object):def findPeakElement(self, nums):""":type nums: List[int]:rtype: int"""for i in range(1,len(nums)):if nums[i] < nums[i - 1]:return i - 1return len(nums) - 1

参考链接:

http://blog.csdn.net/linhuanmars/article/details/20588511 

转载于:https://www.cnblogs.com/kukri/p/8484992.html

Leetcode中几道二分查找(Binary Search)的算法题总结相关推荐

  1. 二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现

    问题背景 今年的实习生招聘考试,我出了一道二分查找(Binary Search)的题目.题目大意如下: 给定一个升序排列的自然数数组,数组中包含重复数字,例如:[1,2,2,3,4,4,4,5,6,7 ...

  2. 八、二分查找(Binary Search)

    一.概述 二分查找(Binary Search,也称折半查找)--针对有序数据集合的查找算法 1.基本思想 类似分治思想,每次都通过跟区间的中间元素进行对比,将代查找的区间缩小为之前的一半,直到找到要 ...

  3. 算法导论第2章(3) 二分查找 binary search

    二分查找(分治法). 二分查找也是一种分治法的实现,每一次查找将数据分为两个部分,问题规模都减小一半.这样查找的时间复杂度为logN.因为其实查找过程建立了一棵有N个节点的二叉树,查找次数是这棵树的高 ...

  4. 二分查找 Binary Search

    明确循环不变量:变量的值可能在变化,但是它的含义是不变的 https://baike.baidu.com/item/循环不变量/8353186?fr=aladdin 如何写出正确的程序? 明确变量的含 ...

  5. leetcode中关于使用二分查找算法思想deal的题型

    学习了二分查找的算法思想之后,再leetcode上写了一道常见的简单面试题,现在用博客记录一下我学习刷题的笔记! leetcode 题号69:Sqrt(x)(经典的面试题) 给你一个非负整数 x ,计 ...

  6. ABAP性能优化之使用二分查找(Binary Search)选项

    READ命令使用顺序查找数据表,这会降低处理速度.取而代之,使用binary search的附加命令,可以使用二分查找算法,可以帮助加快内表查找速度. 在使用binary search之前 必须首先将 ...

  7. SAPABAP性能优化技巧—使用二分查找(Binary Search)选项

    READ命令使用顺序查找数据表,这会降低处理速度.取而代之,使用binary search的附加命令,可以使用二分查找算法,可以帮助加快内表查找速度. 在使用binary search之前必须首先将内 ...

  8. #2020寒假集训#二分入门(Binary Search)代码笔记

    二分查找--Binary Search 原理就类似于下图啦(网上看到哒,忽略这个代价) 二分的时间复杂度一般是 O(logN) 的,超开心了有木有٩(๑>◡<๑)۶ 最简单来说,它可以分为 ...

  9. 【链表递归构造二叉树】LeetCode 109. Convert Sorted List to Binary Search Tree

    LeetCode 109. Convert Sorted List to Binary Search Tree Solution1:我的答案 偷鸡摸狗的做法 /*** Definition for s ...

最新文章

  1. Apache+PHP in MAC
  2. html中利用table进行布局
  3. Dubbo 源码分析 - 集群容错之Directory
  4. 因云而生 | 阿里云发布云服务器操作系统Alinux3
  5. maven的仓库、生命周期与插件
  6. nand linux bbt存储,Linux NAND BBT管理
  7. [Ext JS ][12.13] FieldSet 与 Grid结合 ,实现FieldSet 显示Gird中Store 的数量
  8. ios 添加浮动效果_iOS 为UITableView的索引 添加浮动放大View显示
  9. 折线图x轴的日期会超出_折线图技巧丨阈限颜色设置
  10. idea自动化部署Alibaba Cloud Toolkit
  11. 固态硬盘是什么接口_固态硬盘都有哪些接口,是否通用吗?
  12. ArcMap无法启动解决方法
  13. WFA程序C#窗体间传值
  14. 推荐系统与精细化运营
  15. DB2 sequence 获取下一个值
  16. php期末考试题机考_PHP试题网
  17. java 红外光谱数据库_【分享】免费的20个谱图数据库 - 晶体 - 小木虫 - 学术 科研 互动社区...
  18. 淘宝开放平台开发指南之熟悉API族
  19. 浙江仙居“土味”民俗迎中国年:留住乡愁记忆
  20. 部门新来的00后测试员已把我卷崩溃,老油条表示真干不过,但是...

热门文章

  1. php上传文件产生的临时文件问题,以及所谓的资源类型到底是什么
  2. 新浪实时股票数据接口http://hq.sinajs.cn/list=code
  3. Unity九宫格切割图片 2D Sprite
  4. 黑鲨可以换鸿蒙系统吗,黑鲨游戏手机系统更新:新增人脸识别等功能
  5. linux服务器默认多久断开ssh,SSH超时自动断开问题解决
  6. CDS ORF 启动子 终止子 转录因子 基因结构 UTR
  7. 献给和我一样迷茫的人们,9天准备笔试上岸中科大MPM工程硕士的心路历程(8820字)
  8. Radiology:影像组学:图像不仅仅是图片,它们还是数据
  9. 编程彩虹c语言,c – 如何渲染彩虹光谱?
  10. 新浪云、腾讯云、阿里云、百度云、谷歌云、亚马逊云的区别是什么,哪个更适合国内创业者使用?