二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法,可以在数据规模的对数时间复杂度内完成查找。 二分查找可以应用于数组,是因为数组具有有随机访问的特点,并且数组是有序的。 二分查找体现的数学思想是「减而治之」,可以通过当前看到的中间元素的特点推测它两侧元素的性质,以达到缩减问题规模的效果。 二分查找问题也是面试中经常考到的问题,虽然它的思想很简单,但写好二分查找算法并不是一件容易的事情。 一分为二,进行元素的查找。我们先看如何来写好二分算法。
关键字
查找
分割对半
中间元素(中间指示符)与左右两侧元素的性质,这个决定 low,height 如何变化
使用前提
有序,这个有序是指元素之间 构成前后的逻辑关系。如:排序……
组成部分
模版之间的区别
难点
经典范例 题目:给定一个升序的 nums 数组,和一个 target 值,用二分查找的方式查找该值是否在数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function halfSearch (nums, target ) { let low = 0 ; let height = nums.length - 1 ; while (low <= height) { let mid = Math .floor ((low + height) / 2 ); if (target === nums[mid]) { return mid; } else if (target > nums[mid]) { low = mid + 1 ; } else if (target < nums[mid]) { height = mid - 1 ; } } return -1 ; }
这道题的难点,就是 low,hight 的区间缩放。又发现,无论以哪个点做划分,分割出来的,[0,mid][mid,hight],一部分有序,一部分无序, nums[0]<nums[mid]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 var search = function (nums, target ) { let l = 0 ; let r = nums.length - 1 ; if (nums.length === 1 ) { return nums[0 ] === target ? 0 : -1 ; } while (l <= r) { const mid = l + Math .floor ((r - l) / 2 ); if (nums[mid] === target) return mid; if (nums[0 ] <= nums[mid]) { if (nums[0 ] <= target && target < nums[mid]) { r = mid - 1 ; } else { l = mid + 1 ; } } else { if (nums[mid] < target && target <= nums[nums.length - 1 ]) { l = mid + 1 ; } else { r = mid - 1 ; } } } return -1 ; };
注意
二分,要注意找到分割的点和区间
排序(不一定)好的
对谁划分,一定是有序的对象
判定
初始左右边界
中间元素的特点推测它两侧元素的性质
算术 x 平方根 的整数 暴力 1 到 n 这样直接 每个元素与自身相乘,直到第一个大于或者等于的元素截止。
1 2 3 4 5 6 7 8 9 10 11 12 function violenceSqrt (num ) { let i = 0 ; while (i <= num) { if (i * i >= num) { if (i * i === num) return i; else return i - 1 ; } i++; } return -1 ; }
k*k<=x 我们 以 0 ,x 为区间,找中间值的平方
二分法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 function sqrtNumber (num ) { let i = 0 ; let hight = num; while (i <= hight) { const mid = (i + hight) >> 1 ; if (mid * mid === num) { return mid; } else if (mid * mid < num) { i = mid + 1 ; } else { hight = mid - 1 ; } } return hight; }for (let i = 0 ; i <= 100 ; i++) { console .log ("input" + i, "---val:" + sqrtNumber (i)); }
出题规律
计数,后缀和 首先,我们先明白 count 计数的意义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function specialArray (nums ) { let n = nums.length ; let count = new Array (n + 1 ).fill (0 ); for (let num of nums) { count[Math .min (num, n)]++; } for (let i = n; i >= 0 ; i--) { if (i < n) count[i] += count[i + 1 ]; console .log (i); if (count[i] == i) return i; } return -1 ; }specialArray ([0 , 4 , 3 , 0 , 4 ]);
https://leetcode-cn.com/problems/count-negative-numbers-in-a-sorted-matrix/solution/leetcode-offer-er-fen-cha-zhao-san-da-mo-6rrn/
难点
https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix/
感想,难的太难了…. 如何识别二分查找问题 二分法,分界真是太难找了
我并不懂二分查找
左开右闭,什么玩意都不懂呀,这个其实就是判断比较最后一个元素
搜索区间–“不断缩小”,
二分经典题目