二分查找

二分查找是一种在每次比较之后将查找空间一分为二的算法。每次需要查找集合中的索引或元素时,都应该考虑二分查找。如果集合是无序的,我们可以总是在应用二分查找之前先对其进行排序。
时间复杂度是: log N。因为,二分查找是通过将现有数组一分为二来执行的。每次调用子例程(或完成一次迭代)时,其大小都会减少到现有部分的一半。迭代的最大次数是 log N (base 2) 。

最常用的模板

二分查找一般由三个主要部分组成:

  1. 预处理 —— 如果集合未排序,则进行排序
  2. 二分查找 —— 使用循环或递归在每次比较后将查找空间划分为两半。
  3. 后处理 —— 在剩余空间中确定可行的候选者。

先介绍学校中学习的常用模板(由于每次都判断nums[mid]==target 无需后处理):

public int binarySearch(int[] nums, int target) {int right=nums.length-1;int left=0;while(left<=right){int mid=(left+right)/2;if(nums[mid]==target) return mid;else if(nums[mid]>target) right=mid-1;else left=mid+1;}return -1;}

初始条件:left = 0, right = length-1
终止:left <= right
向左查找:right = mid-1
向右查找:left = mid+1

高阶模板

终止条件修改为:left+1>right始终保留区间内大于两个元素,因此需要对剩下的两个元素进行后处理

int binarySearch(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left + 1 < right){int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid;} else if (nums[mid] < target) {left = mid;} else {right = mid;}}//后处理if(nums[left] == target) return left;if(nums[right] == target) return right;return -1;
}

算法应用

模板一

猜数字:从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。
每次你猜错了,我会告诉你这个数字是大了还是小了。你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0):

public class Solution extends GuessGame {public int guessNumber(int n) {long left=0,right=n;while(left<=right){long mid=(left+right)/2;if(guess((int)mid)==0)return (int)mid;else if(guess((int)mid)==-1)right=mid-1;elseleft=mid+1;}return -1;}
}

模板二

寻找峰值:峰值元素是指其值大于左右相邻值的元素。
要求:给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。你可以假设 nums[-1] = nums[n] = -∞。

class Solution {public int findPeakElement(int[] nums) {if(nums==null) return -1;if(nums.length==1) return 0;int left=0,right=nums.length;while(left+1<right){int mid= left+(right-left)/2;if((mid-1==-1||nums[mid]>nums[mid-1])&&   //mid-1可能越界,先做判断(mid+1==nums.length||nums[mid]>nums[mid+1]))return mid;else if (nums[mid]<nums[mid-1])right=mid;elseleft=mid;}if(left-1==-1||nums[left]>nums[left-1]&&nums[left]>nums[left+1])return left;if(nums[right]>nums[right-1]&&right+1==nums.length||nums[right]>nums[right+1])return right;return -1;}
}

核心:分治思想

二分查找的核心思想就是分治思想

pow(n,x)

分治思想还可以解决其他的一些问题:pow(n,x)的实现,即计算 x 的 n 次幂函数。

class Solution {public double myPow(double x, int n) {return n>0?quickMul(x,n):1/quickMul(x,-n);}public double quickMul(double x, int n){if(n==0) return 1;if(n==1) return x;double y=quickMul(x,n/2);return n%2==0?y*y:y*y*x;}
}

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

给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。
在比较时,字母是依序循环出现的。举个例子:
如果目标字母 target = ‘z’ 并且字符列表为 letters = [‘a’, ‘b’],则答案返回 ‘a’.

class Solution {public char nextGreatestLetter(char[] letters, char target) {int left=0,right=letters.length-1,mid=0;while(left<=right){mid=left+(right-left)/2;if(letters[mid]==target){while(mid+1<letters.length&&letters[mid]==letters[mid+1])mid++;break;}else if(letters[mid]<=target)left=mid+1;elseright=mid-1;}if(target<letters[mid])return letters[mid];return letters[(mid+1)%letters.length];}
}

二分搜索——分治思想相关推荐

  1. 006.递归和分治思想

    为什么80%的码农都做不了架构师?>>>    斐波那契数列的递归实现  迭代实现  递归   1.递归 定义 迭代使用的是循环结构. 递归使用的是选择结构. 优点 使用递归 ...

  2. 递归和分治思想及其应用

    目录 递归和分治思想 一些实例 逆序输出字符串 查找数组元祖是否存在 汉诺塔问题 八皇后问题 更多: 递归和分治思想 如果可以使用迭代,尽量别使用递归.由编译原理可以知道,每次自调用的时候,计算机都需 ...

  3. 【算法】学习笔记(4):分治思想 归并排序

    分治思想,分治策略,自古有之,与人类生活息息相关,其本质是将大问题拆解为小问题,小问题转换为已知解的问题,进而求解. 军队管理,国家分级治理-- 大规模数据排序,例如10000000000万个数,规模 ...

  4. 使用分治思想求解最大子序列

    本文使用分治思想求解一个整型数组中的最大子序列,该算法的时间复杂度为NlogN,使用千万级的数据量计算结果的时间不超过0.5s.该算法使用了分治的思想:求解最大子序列的问题可以理解为将整个数组分成左右 ...

  5. 算法设计与分析:分治思想 - 入门

    文章目录 分治思想 判断分治的条件 分治思想在排序问题的应用 求逆序对的个数 分治总结 本文参考UCAS卜东波老师的计算机算法设计与分析课程完成 分治思想 分治思想可以归纳为两点: 将一个复杂问题化简 ...

  6. 汉诺塔问题——分治思想

    汉诺塔规则如下: 1.有三根相邻的柱子,标号为x,y,z. 2.x柱子上从下到上按金字塔状叠放着n个不同大小的圆盘. 3.现在把所有盘子一个一个移动到柱子z上,并且每次移动同一根柱子上都不能出现大盘子 ...

  7. 分治思想应用:数学归纳法、递归、归并排序、MapReduce

    跟黄申老师学数学系列02(python实现) 引言: 数学归纳法(Mathematical Induction).递归.归并排序(merge sort).MapReduce,这些方法或技术都基于一个重 ...

  8. 线性时间选择算法的分治思想:邮局选址问题和士兵战队问题

    一. 实验题目 1. 邮局选址问题 在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分 布在不同的街区中.用 x 坐标表示东西向,用 y 坐标表示南北向.各居民点的 位置可以由坐标( ...

  9. 【PTA】7-2 国王的奖励——分数取模、分治思想、快速幂、int64的乘法模运算【C/C++】

    文章目录 1 问题 1.1 题面描述 1.2 输入描述 1.3 输出描述 1.4 样例描述 1.5 样例解释 2 分析 2.1 数学抽象 2.2 解决方法 2.2.1 等比求和 2.2.1.1 求和公 ...

最新文章

  1. html如何制作查看更多横条,页面浏览量顶部横条显示代码-附“Js/Jquery获取网页屏幕可见区域高度”...
  2. 基于OpenResty的弹性网关实践(一)
  3. 九、为了OFFER而战,那些日子在牛客网刷Linux面试题(下)
  4. 利用 LotusScript 灵活操作 Lotus Notes 富文本域
  5. Java8学习笔记(1) -- 从函数式接口说起
  6. Taro+react开发(53) Taro提示操作
  7. 2017.08.15【NOIP提高组】模拟赛B组 生日聚餐
  8. python unique函数_《Python编程从入门到实践》json数据可视化练习详解
  9. android 开发50个技巧面向切面编程思想
  10. 云计算创业在美国真是如火如荼。
  11. 深入浅出MFC 书中源码Frame1(C++11)
  12. 写贺卡给毕业师姐怎么写计算机系的,师哥送下一届毕业的寄语
  13. 《自由在高处》读后感
  14. 【BUUCTF】CTF_Crypto 密码学_Quoted-printable(引用可打印)
  15. 软件是用计算机解决问题,电脑常见的软件问题及解决方法
  16. Python爬虫获取企查查公开的企业信息
  17. 题解_UVA_11134_Fabled Rooks
  18. 关于数据治理的读书笔记 - 什么是数据治理?
  19. 【性能优化】PHP - 优化手段 - 学习/实践
  20. 2021年安全员-C证(山东省-2021版)找解析及安全员-C证(山东省-2021版)模拟考试

热门文章

  1. ASEMI大功率三相整流桥D30XT80的使用教程
  2. 洛谷 2341受欢迎的牛
  3. Android 多屏适配解决方案
  4. 时序数据库TSDB按时间进行数量统计算法研究
  5. 行为管理(锐捷云桌面2)
  6. 22岁初中学历怎么提升大专学历 报名步骤有哪些
  7. 11 突变 Somatic Signature 图谱
  8. c语言指令ASCA,吉林大学C语言习题.doc
  9. linux进阶-AIDE命令小结
  10. 忘不了手机随身私密管家,懒人必备神器