二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。
前提:数组有序
思路:
- 定义常量:数组查找开始和结束位置;
- while循环:只要开始位置<=结束位置,计算中间位置(注意:要用Math.floor,不然所求会是小数),则比较所要查找值与中间值位置大小
- 如果中间位置不是所求,即重新赋值开始或者结束位置索引
二分法查找的时间复杂度O(logn)。
<!DOCTYPE html>
<html>
<script>
// 二分查找
function getIndex(arr, num) {
const [arrLen, start, end] = [arr.length, 0, arr.length - 1];
while (start <= end) {
mid = Math.floor((start + end) / 2);
if (num < arr[mid]) {
end = mid - 1;
} else if (num > arr[mid]) {
start = mid + 1;
} else {
return mid;
}
}
return -1;
}
const arr1 = [1, 2, 3, 4, 5, 6];
console.log(getIndex(arr1, 3)); // 2
const arr2 = [1, 4, 7, 8, 12, 34, 67, 88, 99, 100]
console.log(getIndex(arr2, 12)); // 4
const arr3 = [1]
console.log(getIndex(arr3, 1)); // 0
const arr4 = []
console.log(getIndex(arr4, 12)); // -1
</script>
</html>
之前总是什么都不返回,是因为一开始并不是一找到就返回,而是定义了一个局部变量使:numIndex = mid;这样就没有即是停止循环,导致最终无结果。
如果题目换成,给定一个有序数组,找出给定值的最大index呢?
<!DOCTYPE html>
<html>
<script>
// 二分查找,最大索引
function getIndex(arr, num) {
let maxIndex = -1;
let [start, end] = [0, arr.length - 1];
while (start <= end) {
mid = Math.floor((start + end) / 2);
if (arr[mid] <= num) {
start = mid + 1;
if (num === arr[mid]) {
maxIndex = mid;
}
} else {
end = mid - 1;
}
}
return maxIndex;
}
const arr1 = [1, 2, 3, 3, 3, 3, 4, 5, 6];
console.log(getIndex(arr1, 3)); // 5
const arr11 = [1, 2, 3, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10];
console.log(getIndex(arr1, 3)); // 5
const arr2 = [1, 4, 7, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 34, 67, 88, 99, 100]
console.log(getIndex(arr2, 12)); // 12
const arr3 = [1]
console.log(getIndex(arr3, 1)); // 0
const arr4 = []
console.log(getIndex(arr4, 12)); // -1
</script>
</html>
注意:判断条件不能用 if (num <= arr[mid] ) ,因为,如果正好num === arr[mid],索引只会越找越小;但是用代码中判断条件,索引会越找越大,符合题意。