二分查找

【学习笔记】二分查找

限于喜欢 提交于 2019-11-29 16:34:44
二分查找的学习笔记 之前在bilibili看到一个有趣的视频,关于二分查找的。 戳我看这个有趣的视频 笔记参考:极客时间|数据结构与算法之美 1. 二分思想 就如上面视频中的栗子,猜数字游戏,如果从头开始一个一个的猜是非常低效的。 在实际的开发场景中,假设有1w条订单数据,已经按照订单的金额从小到大排序,每个定干的金额不同,最小单位是元。 如果从第一个订单开始,遍历这1w条订单,直到找到目标为止,这种方法在最坏情况下可能要便利完所有数据才能找到。 但是用二分法,每次都通过跟区间中间元素对比,将整个带查找的区间缩小为之前的一半,直到查找的需要的数据或者区间缩小为0。 2. 二分查找实现(递归和非递归) // 非递归实现 int bsearch ( int a [ ] , int n , int value ) { int low = 0 ; int high = n - 1 ; while ( low <= high ) { int mid = ( low + high ) / 2 ; if ( a [ mid ] == value ) { return mid ; } else if ( a [ mid ] < value ) { low = mid + 1 ; } else { high = mid - 1 ; } } /*while*/ return - 1 ; }

|算法讨论|二分查找 学习笔记

橙三吉。 提交于 2019-11-29 16:33:44
以下程序对比了lower_bound和自写函数的比较,基本上能够保证正确 #include<cstdio> #include<cstring> #include<algorithm> #include<ctime> using namespace std; #define ms(i,j) memset(i,j,sizeof i); const int MAXN = 1000 ; int n = 20 ; int a[MAXN]; int rightans; int cans; int bs( int begin, int end, int x ) { int l = begin, r = end; int mid; while (l<r)//如果是浮点数,换成 for ( int i= 0 ;i< 100 ;i++) {即可 mid = (l+r)/ 2 ; if ( x >a[mid]) l = mid+ 1 ; else r = mid; } return r; } int main() { //freopen ( ".in" , "r" , stdin); freopen( ".out" , "w" , stdout); srand (( int ) time ( 0 )); for (;;) { for ( int i= 0 ;i<n;i++) a[i] = rand ()

二分查找 学习笔记

主宰稳场 提交于 2019-11-29 16:30:52
二分查找,即对一个有序序列在中间对分,判断该值属于那另一半。(有序很重要) 二分查找找到数据需要用几步的计算。 用二分查找最多需要:log以2为底N的对数。 来源: CSDN 作者: 不要怂,就是干 链接: https://blog.csdn.net/weixin_42013825/article/details/87900714

二分查找(折半查找)——查找每个元素的比较次数

孤者浪人 提交于 2019-11-29 15:06:36
基本思想 首先将给定值K与表中中间位置的关键字比较,若相等,则查找成功,返回该元素的下标;若不等,则所查找的元素只能在中间数据以外前半部分或后半部分。然后在缩小的区间中继续进行同样的查找,如此重复直到找到为止,如果查找区间缩小到只有一个元素,其关键字仍不等于k,则查找失败 。 每进行一次键值与给定值的比较,查找区间的长度至少减少为原来的二分之一。 题目 用二分查找法对一个长度为10的有序表进行查找,填写每一元素需要比较次数,元素下表: 1 2 3 4 5 6 7 8 9 10 填写比较次数 Mid=(low+high)/2,在每次比较是可以根据区间查找,如果为奇数的是去最中间一个,若是偶数则向下取整。 第一次 Mid(1+9)/2=5 取第五个数,再此序列的值为5 1 low 2 3 4 5 mid 6 7 8 9 10 high 将此无序序列分成两组,即5之前为一组,5之后为一组。 第二次 ,先排左边 1 low 2 3 4 5 mid 6 7 8 9 10 high Mid(1+4)/2=2.5取2.即2的位置 1 low 2 mid 3 4 high 第三次 在第三趟的时候mid左边只有一个数,即low,high,mid都是这一个数,所以在第三趟的时候1的比较次数已经出来了,接下来就开始比较右边的。 Mid(1+2)/2=1.5 还是向下取整,为1 1 low Mid

二分查找

可紊 提交于 2019-11-29 15:03:14
寻找有序序列中第一个满足某条件的元素的位置 二分的区间是答案可能出现的区间,而不是(不一定是)有序序列的区间,比如说,对于“寻找序列中第一个大于等于 x 的元素的位置( lower_bound )”这个问题,如果给定有序序列的范围是 [ 0 , n − 1 ] [0,n-1] [ 0 , n − 1 ] ,那么考虑到 x 有可能比这个序列中所有的数都要大,实际上答案的范围是 [ 0 , n ] [0,n] [ 0 , n ] 。 不管是什么形式的区间, while 循环进行的条件永远都是 是否找到了唯一的位置 ,也就是待二分的区间是否可以夹出唯一的位置。 给 right 或 left 赋值,实际上是选择左区间或者右区间,然后继续二分。要注意,赋值之后区间的形式要保持统一,比如一开始区间是左闭右开,那么赋值之后仍应该是左闭右开的。 这类问题有几个常见的算法: lower_bound 寻找第一个大于等于x的元素的位置 upper_bound 寻找第一个大于x的元素的位置 这两个函数在 <algorighm> 中均有实现,且 参数区间范围均是左闭右开 ,也就是说,答案的范围相当于同一个区间的左闭右闭。 // 寻找有序序列第一个满足某条件的元素的位置 int solve (int left, int right) { int mid; while (没有找到唯一位置) { mid =

leetcode刷题 二分查找

隐身守侯 提交于 2019-11-29 11:17:40
作为本科非科班出身的CSer也经历了看到leetcode不知从何刷起的感觉,现在准备重新刷一下leetcode,写博客主要是记录下自己的思路,尽量保持每天两道,这篇主要总结二分查找所遇到的问题以及变种。 打个广告微博 @辣酱一直就这样 欢迎同学私信讨论 先说一下二分查找的模版 1. start + 1 < end //在相邻的时候退出避免死循环 2. start + (end - start) / 2 //找中间值,装逼写法避免mid比Integer.max_value还大导致溢出 3. A[mid] ==, <, >//判断要根据找target是第一次出现还是最后一次出现来决定把mid 给start 还是end 4. A[start] A[end] ? target//最后相邻退出同样要考虑是找target第一次出现还是最后一次出现. 二分查找基本题型,leetcode上面好像没有,我找了lintcode上面一道 http://www.lintcode.com/zh-cn/problem/first-position-of-target/# 这道题就是最基本的二分查找,target有重复,需要找到target第一次出现时所在数组的下标,很简单套模版 class Solution { /** * @param nums: The integer array. * @param

web前端知识体系之基础知识 -JavaScript旋转数组最小的数字

旧时模样 提交于 2019-11-29 10:28:24
1. 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为 1。 2. 解题思路 最简单的肯定是从头到尾遍历,复杂度是 O(N) 。 这种方法没有利用“旋转数组”的特性 。 借助二分查找的思想,时间复杂度可以降低到 O(log(N)) 。 可以通过以下方法确定最小值元素的位置,然后移动指针,缩小范围: 中间指针对应的元素 ≥ 左侧元素, 那么中间元素位于原递增数组中, 最小值在右侧 中间指针对应的元素 ≤ 右侧元素, 那么中间元素位于被移动的递增数组中,最小值在左侧 特殊情况,如果三者相等,那么无法判断最小值元素的位置,就退化为普通遍历即可。 3. 代码 先上一段二分查找和实现思路: /** * 二分查找 * @param {Array} arr * @param {*} elem */ function binarySearch(arr, elem) { let left = 0, right = arr.length - 1, mid = -1; while (left <= right) { // 注意是≤:考虑只剩1个元素的情况 mid = Math.floor((left + right) / 2); if

二分查找——三种模板(C++版本)

坚强是说给别人听的谎言 提交于 2019-11-29 08:12:53
模板一: int binarySearch(vector<int>& nums, int target){ if(nums.size() == 0) return -1; int left = 0, right = nums.size() - 1; while(left <= right){ // Prevent (left + right) overflow int mid = left + (right - left) / 2; if(nums[mid] == target){ return mid; } else if(nums[mid] < target) { left = mid + 1; } else { right = mid - 1; } } // End Condition: left > right return -1; } 模板二: int binarySearch(vector<int>& nums, int target){ if(nums.size() == 0) return -1; int left = 0, right = nums.size(); while(left < right){ // Prevent (left + right) overflow int mid = left + (right - left) / 2; if(nums

Java实现二分查找

微笑、不失礼 提交于 2019-11-29 00:22:38
二分查找又称折半查找,查找效率不错 适用场景:顺序存储结构且按有序排列,这也是它的缺点。 demo如下: package 数据结构算法.查找; public class binarySearch { public static void main(String[] args) { int[] array ={1,2,3,4,6,7,8,9,10}; System.out.println( binSearch_2(3,array,0,array.length-1)); System.out.println( binSearch_2(5,array,0,array.length-1)); } /* *循环实现二分算法 */ public static int binSearch_1(int key, int[] array) { int low = 0; //第一个下标 int high = array.length - 1;//最后一个下标 int middle = 0; //防越界 if (key < array[low] || key > array[high] || low > high) { return -1; } while (low <= high) { middle = (low + high) / 2; if (middle == key) { return

二分查找

大城市里の小女人 提交于 2019-11-29 00:08:05
二分查找,是在数组有序基础上建立的。 算法思想: 搜索过程中从数组的中间元素开始,如果中间元素正好是 num,搜索过程结束。 如果目标值 > 中间元素,则从 [中间元素,右边界 R ]中取中间值,再比较。 如果某一步骤为空,则代表找不到。 这种搜索算法,每一次比较都使搜索范围小一半。 实现思路: 找出数组中间的值,并存放到一个变量中(temp) 需要找到 key 和 temp 比较: key > temp ,[key ,右边界] 找中间值,循环。 如果 key = temp ,返回数组下标,找到成功。 package suanfa; public class BinarySearch { public static int binarySearch(int[] arr, int key) { int L = 0; int R = arr.length - 1; int middle = 0; if (L > R || key < arr[L] || key > arr[R]) { return -1; } while (L < R) { middle = (L + R) / 2; if (key > arr[middle]) { L = middle + 1; } else if (key < arr[middle]) { R = middle - 1; } else {