Skip to content

Commit 24a5dc9

Browse files
committed
feat(binary-search): 📝总结二分搜索简单篇
1 parent bd6c2c0 commit 24a5dc9

13 files changed

+162
-76
lines changed

Binary-Search/367.png

141 KB
Loading

Binary-Search/367/solution1.js

+9-16
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,18 @@
99
* 33.8mb 79.73%
1010
*/
1111
const isPerfectSquare = num => {
12-
// 边界情况
13-
if (num === 1) {
14-
return true
15-
}
16-
let first = 1
17-
let last = num
12+
let start = 1
13+
let end = num
1814

19-
while (first < last) {
20-
const mid = Math.floor(first + (last - first) / 2)
21-
const ret = mid * mid
22-
if (ret === num) {
23-
return true
24-
}
25-
if (ret > num) {
26-
last = mid
15+
while (start < end) {
16+
const mid = Math.floor(start + (end - start) / 2)
17+
const middle = mid * mid
18+
if (num > middle) {
19+
start = mid + 1
2720
} else {
28-
first = mid + 1
21+
end = mid
2922
}
3023
}
3124

32-
return false
25+
return start ** 2 === num
3326
}

Binary-Search/441/solution1.js

+11-16
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,20 @@
1212
*/
1313

1414
const arrangeCoins = n => {
15-
// 边界情况
16-
if (n === 0) {
17-
return 0
18-
}
19-
if (n === 1) {
20-
return 1
21-
}
22-
let first = 0
23-
let last = n
24-
let ret = 0
25-
while (first < last) {
26-
const mid = Math.floor(first + (last - first) / 2)
15+
let start = 0
16+
let end = n
17+
while (start < end) {
18+
const mid = Math.floor(start + (end - start) / 2)
2719
const target = (mid + 1) * mid / 2
28-
if (target > n) {
29-
last = mid
20+
if (n > target) {
21+
start = mid + 1
3022
} else {
31-
first = mid + 1
23+
end = mid
3224
}
3325
}
3426

35-
return first - 1
27+
if ((start + 1) * start / 2 > n) {
28+
return start - 1
29+
}
30+
return start
3631
}

Binary-Search/475.png

348 KB
Loading

Binary-Search/475/solution1.js

+14-17
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/**
2-
* https://leetcode.com/problems/heaters/
32
*
43
* 475. Heaters
54
*
65
* Easy
76
*
8-
* 112ms 90.01%
7+
* 184ms 100.00%
98
* 39mb 74.45%
109
*/
1110
const findRadius = (houses, heaters) => {
@@ -16,14 +15,15 @@ const findRadius = (houses, heaters) => {
1615

1716
for (let i = 0, max = houses.length; i < max; i++) {
1817
const house = houses[i]
19-
const first = binarySearch(heaters, 0, len - 1, house)
18+
const targetPos = binarySearch(heaters, 0, len - 1, house)
2019
let closestDistance = Number.MAX_SAFE_INTEGER
21-
if (first === undefined) {
20+
if (heaters[targetPos] === house) {
2221
ans = Math.max(ans, 0)
2322
continue
2423
}
25-
const pre = heaters[first - 1]
26-
const cur = heaters[first]
24+
// 比较前一个 和 后一个 得到最小值
25+
const pre = heaters[targetPos - 1]
26+
const cur = heaters[targetPos]
2727
if (pre !== undefined) {
2828
closestDistance = Math.min(closestDistance, Math.abs(house - pre))
2929
}
@@ -35,18 +35,15 @@ const findRadius = (houses, heaters) => {
3535
return ans
3636
}
3737

38-
function binarySearch(array, first, last, target) {
39-
while (first < last) {
40-
const mid = Math.floor(first + (last - first) / 2)
41-
const t = array[mid]
42-
if (t === target) {
43-
return undefined
44-
}
45-
if (t > target) {
46-
last = mid
38+
function binarySearch(array, start, end, target) {
39+
while (start < end) {
40+
const mid = Math.floor(start + (end - start) / 2)
41+
const middle = array[mid]
42+
if (target > middle) {
43+
start = mid + 1
4744
} else {
48-
first = mid + 1
45+
end = mid
4946
}
5047
}
51-
return first
48+
return start
5249
}

Binary-Search/69/solution1.js

+12-16
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,20 @@
99
* 35.7mb 47.66%
1010
*/
1111
const mySqrt = x => {
12-
if (x === 1) {
13-
return 1
14-
}
15-
let first = 1
16-
let last = x
12+
let start = 1
13+
let end = x
1714

18-
while (first < last) {
19-
const mid = Math.floor(first + (last - first) / 2)
20-
const target = mid * mid
21-
if (target === x) {
22-
return mid
23-
}
24-
if (target > x) {
25-
last = mid
15+
while (start < end) {
16+
const mid = Math.floor(start + (end - start) / 2)
17+
const middle = mid * mid
18+
if (x > middle) {
19+
start = mid + 1
2620
} else {
27-
first = mid + 1
21+
end = mid
2822
}
2923
}
30-
31-
return first - 1
24+
if (start ** 2 === x) {
25+
return start
26+
}
27+
return start - 1
3228
}

Binary-Search/744.png

190 KB
Loading

Binary-Search/852.png

150 KB
Loading

Binary-Search/852/solution2.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ const peakIndexInMountainArray = A => {
1212
return binarySearch(A, 0, A.length - 1)
1313
}
1414

15-
function binarySearch(array, first, end) {
16-
while (first < end - 1) {
17-
const mid = Math.floor(first + (end - first) / 2) // 数组下标注意整数
15+
function binarySearch(array, start, end) {
16+
while (start < end) {
17+
const mid = Math.floor(start + (end - start) / 2)
1818
if (array[mid + 1] > array[mid]) {
19-
first = mid
19+
start = mid + 1
2020
} else {
2121
end = mid
2222
}
2323
}
2424

25-
return (array[first] > array[end] ? first : end)
25+
return start
2626
}
4.95 KB
Loading

Binary-Search/index.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function binarySearch(arr, target) {
2+
let start = 0
3+
let end = arr.length - 1
4+
5+
while (start < end) {
6+
const mid = Math.floor(start + (end - start) / 2)
7+
if (arr[mid] < target) {
8+
start = mid + 1
9+
} else {
10+
end = mid
11+
}
12+
}
13+
14+
return start
15+
}
16+
17+
console.log(binarySearch([0, 1, 2, 3, 4, 5], 5))

Binary-Search/readme.md

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# 一只前端的 LeetCode 之旅 -- 二分搜索(Easy篇)
2+
3+
### 一、二分搜索算法
4+
5+
##### 1、基本认知
6+
7+
&emsp;&emsp;二分搜索是一种在有序数组中查找某一特定元素的搜索算法。
8+
9+
![二分搜索](./Binary_search_into_array.png)
10+
11+
&emsp;&emsp;二分搜索算法的时间复杂度为 O(log n),相比较顺序搜索的 O(n) 时间复杂度,它是非常快的。
12+
13+
&emsp;&emsp;例如,在一个长度为一百万的有序数组中,采用顺序搜索,最坏的情况需要执行一百万次,而二分搜索算法则只需要二十次!
14+
15+
&emsp;&emsp;从上图中,读者可以发现,二分搜索的关键就是通过目标值与中间值的比较,将搜索区间缩小一半,这也是为什么有序数组是二分搜索算法的重要前提。
16+
17+
##### 2、代码实现
18+
19+
&emsp;&emsp;由前文可知,二分搜索并不是一个特别的复杂的算法,但是想通过代码实现它,并不是一件易事。
20+
21+
&emsp;&emsp;一般二分搜索都是作用于数组上,所以要先求出数组的中间下标(整数),从而获取到中间值:
22+
23+
```JavaScript
24+
const mid = Math.floor((start + end) / 2)
25+
```
26+
27+
&emsp;&emsp;读者可能第一时间想到的就是上述写法,但是在一些极端的情况,start + end 可能直接超出最大的安全整数,所以更加的谨慎的写法如下:
28+
29+
```JavaScript
30+
const mid = Math.floor(start + (end - start) / 2)
31+
```
32+
33+
&emsp;&emsp;最后就是搜索区间如何不断缩小一半,对于很多初学者来说,经常会将其写成一个死循环,这里保持搜索区间左闭右开的写法:
34+
35+
```JavaScript
36+
while (start < end) {
37+
const mid = Math.floor(start + (end - start) / 2)
38+
if (arr[mid] < target) {
39+
start = mid + 1
40+
} else {
41+
end = mid
42+
}
43+
}
44+
```
45+
46+
### 二、LeetCode 实战
47+
48+
##### 1、744. 寻找比目标字母大的最小字母
49+
50+
&emsp;&emsp;这道题目主要考察二分搜索算法的基本实现:
51+
52+
![744解题代码](./744.png)
53+
54+
##### 2、367. 有效的完全平方数
55+
56+
&emsp;&emsp;这道题目需要如下两个技巧:
57+
58+
- 如果 num 为完全平方数,那么能形成该完全平方数的整数必定存在 [1, num) 区间,是不是有序数组的前提条件有了;
59+
- 取得 [1, num) 区间的中间值时,需要进行平方运算后再与 num 比较;
60+
61+
![367解题代码](./367.png)
62+
63+
&emsp;&emsp;类似解题思路的题目还有[【69. x 的平方根】](https://leetcode-cn.com/problems/sqrtx/)[【441. 排列硬币】](https://leetcode-cn.com/problems/arranging-coins/)
64+
65+
##### 3、852. 山脉数组的峰顶索引
66+
67+
&emsp;&emsp;仔细读题之后,你会发现给定的数组并非有序数组,但是需要查找目标数字恰巧处于一个很特殊的位置,当我们从当前区间查找到中间值时,可以通过与前一个数或者后一个数的比较,可以判断当前中间值处于递增还是递减区间,从而判断峰值处于左半区间还是右半区间:
68+
69+
![852解题代码](./852.png)
70+
71+
##### 6、475. 供暖器
72+
73+
&emsp;&emsp;这道题的难点在于是否读懂了题目:找到一个最小半径使得加热器覆盖所有房子。
74+
75+
&emsp;&emsp;那么最简单的解法就是遍历所有的房子的同时,遍历加热器找出距离该房子的最小距离,那么所有房子中的最大距离即为加热器覆盖的最小半径,那么整个过程的时间复杂度就是 O(n*m),对于加热器的搜索可以采用二分搜索算法优化,那么时间复杂度可以优化为 O(nlog m):
76+
77+
![475解题代码](./475.png)
78+
79+
80+
### 写在最后
81+
82+
&emsp;&emsp;算法作为计算机的基础学科,用 JavaScript 刷,一点也不丢人ε=ε=ε=┏(゜ロ゜;)┛。
83+
84+
&emsp;&emsp;本系列文章会分别给出一种算法的3种难度的总结篇(简单难度,中等难度以及困难难度),如果本文对您有所帮助,可以点赞或者关注来鼓励博主。
85+
86+
87+
- [一只前端的 LeetCode 之旅](https://github.com/15751165579/LeetCode)
88+

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
| 题目 | 难度 | 代码 | beats Runtime | beats Memory | 时间复杂度 |
88
| :----- | :---: | :---: | :---: | :---: | :--: |
9-
| [852. Peak Index in a Mountain Array](https://leetcode.com/problems/peak-index-in-a-mountain-array/) | Easy | [解题代码](/Binary-Search/852/solution2.js) | **98.70%** | **72.89%** | O(log n)|
10-
| [744. Find Smallest Letter Greater Than Target](https://leetcode.com/problems/find-smallest-letter-greater-than-target/) | Easy | [解题代码](/Binary-Search/744/solution1.js) | **100.00%** | **72.67%** | O(log n)|
11-
| [367. Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) | Easy | [解题代码](/Binary-Search/744/solution1.js) | **99.67%** | **79.73%** | O(log n)|
12-
| [441. Arranging Coins](https://leetcode.com/problems/arranging-coins/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **100.00%** | **90.18%** | O(log n)|
13-
| [475. Heaters](https://leetcode.com/problems/heaters/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **90.01%** | **74.45%** | O(nlog n)|
14-
| [69. Sqrt(x)](https://leetcode.com/problems/sqrtx/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **96.10%** | **47.66%** | O(log n)|
9+
| [852. 山脉数组的峰顶索引](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/submissions/) | Easy | [解题代码](/Binary-Search/852/solution2.js) | **98.70%** | **72.89%** | O(log n)|
10+
| [744. 寻找比目标字母大的最小字母](https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target/) | Easy | [解题代码](/Binary-Search/744/solution1.js) | **100.00%** | **72.67%** | O(log n)|
11+
| [367. 有效的完全平方数](https://leetcode-cn.com/problems/valid-perfect-square/) | Easy | [解题代码](/Binary-Search/744/solution1.js) | **99.67%** | **79.73%** | O(log n)|
12+
| [441. 排列硬币](https://leetcode-cn.com/problems/arranging-coins/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **100.00%** | **90.18%** | O(log n)|
13+
| [475. 供暖器](https://leetcode-cn.com/problems/heaters/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **90.01%** | **74.45%** | O(nlog m)|
14+
| [69. x 的平方根](https://leetcode-cn.com/problems/sqrtx/) | Easy | [解题代码](/Binary-Search/441/solution1.js) | **96.10%** | **47.66%** | O(log n)|
1515
| [378. Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) | Medium | [解题代码](/Binary-Search/378/solution2.js) | **97.86%** | **73.13%** | O(nlog n)|
1616
| [875. Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/) | Medium | [解题代码](/Binary-Search/875/solution2.js) | **91.82%** | **71.83%** | O(nlog n)|
1717
| [436. Find Right Interval](https://leetcode.com/problems/find-right-interval/) | Medium | [解题代码](/Binary-Search/436/solution2.js) | **100.00%** | **60.00%** | O(nlog n)|

0 commit comments

Comments
 (0)