二分搜索——分治思想
二分查找
二分查找是一种在每次比较之后将查找空间一分为二的算法。每次需要查找集合中的索引或元素时,都应该考虑二分查找。如果集合是无序的,我们可以总是在应用二分查找之前先对其进行排序。
时间复杂度是: log N。因为,二分查找是通过将现有数组一分为二来执行的。每次调用子例程(或完成一次迭代)时,其大小都会减少到现有部分的一半。迭代的最大次数是 log N (base 2) 。
最常用的模板
二分查找一般由三个主要部分组成:
- 预处理 —— 如果集合未排序,则进行排序
- 二分查找 —— 使用循环或递归在每次比较后将查找空间划分为两半。
- 后处理 —— 在剩余空间中确定可行的候选者。
先介绍学校中学习的常用模板(由于每次都判断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];}
}
二分搜索——分治思想相关推荐
- 006.递归和分治思想
为什么80%的码农都做不了架构师?>>> 斐波那契数列的递归实现  迭代实现  递归   1.递归 定义 迭代使用的是循环结构. 递归使用的是选择结构. 优点 使用递归 ...
- 递归和分治思想及其应用
目录 递归和分治思想 一些实例 逆序输出字符串 查找数组元祖是否存在 汉诺塔问题 八皇后问题 更多: 递归和分治思想 如果可以使用迭代,尽量别使用递归.由编译原理可以知道,每次自调用的时候,计算机都需 ...
- 【算法】学习笔记(4):分治思想 归并排序
分治思想,分治策略,自古有之,与人类生活息息相关,其本质是将大问题拆解为小问题,小问题转换为已知解的问题,进而求解. 军队管理,国家分级治理-- 大规模数据排序,例如10000000000万个数,规模 ...
- 使用分治思想求解最大子序列
本文使用分治思想求解一个整型数组中的最大子序列,该算法的时间复杂度为NlogN,使用千万级的数据量计算结果的时间不超过0.5s.该算法使用了分治的思想:求解最大子序列的问题可以理解为将整个数组分成左右 ...
- 算法设计与分析:分治思想 - 入门
文章目录 分治思想 判断分治的条件 分治思想在排序问题的应用 求逆序对的个数 分治总结 本文参考UCAS卜东波老师的计算机算法设计与分析课程完成 分治思想 分治思想可以归纳为两点: 将一个复杂问题化简 ...
- 汉诺塔问题——分治思想
汉诺塔规则如下: 1.有三根相邻的柱子,标号为x,y,z. 2.x柱子上从下到上按金字塔状叠放着n个不同大小的圆盘. 3.现在把所有盘子一个一个移动到柱子z上,并且每次移动同一根柱子上都不能出现大盘子 ...
- 分治思想应用:数学归纳法、递归、归并排序、MapReduce
跟黄申老师学数学系列02(python实现) 引言: 数学归纳法(Mathematical Induction).递归.归并排序(merge sort).MapReduce,这些方法或技术都基于一个重 ...
- 线性时间选择算法的分治思想:邮局选址问题和士兵战队问题
一. 实验题目 1. 邮局选址问题 在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分 布在不同的街区中.用 x 坐标表示东西向,用 y 坐标表示南北向.各居民点的 位置可以由坐标( ...
- 【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 求和公 ...
最新文章
- html如何制作查看更多横条,页面浏览量顶部横条显示代码-附“Js/Jquery获取网页屏幕可见区域高度”...
- 基于OpenResty的弹性网关实践(一)
- 九、为了OFFER而战,那些日子在牛客网刷Linux面试题(下)
- 利用 LotusScript 灵活操作 Lotus Notes 富文本域
- Java8学习笔记(1) -- 从函数式接口说起
- Taro+react开发(53) Taro提示操作
- 2017.08.15【NOIP提高组】模拟赛B组 生日聚餐
- python unique函数_《Python编程从入门到实践》json数据可视化练习详解
- android 开发50个技巧面向切面编程思想
- 云计算创业在美国真是如火如荼。
- 深入浅出MFC 书中源码Frame1(C++11)
- 写贺卡给毕业师姐怎么写计算机系的,师哥送下一届毕业的寄语
- 《自由在高处》读后感
- 【BUUCTF】CTF_Crypto 密码学_Quoted-printable(引用可打印)
- 软件是用计算机解决问题,电脑常见的软件问题及解决方法
- Python爬虫获取企查查公开的企业信息
- 题解_UVA_11134_Fabled Rooks
- 关于数据治理的读书笔记 - 什么是数据治理?
- 【性能优化】PHP - 优化手段 - 学习/实践
- 2021年安全员-C证(山东省-2021版)找解析及安全员-C证(山东省-2021版)模拟考试