概念
二分查找的思路是很简单的,前提是这组数据是有顺序的。 思路是从中间找一个数,判断大小,如果数比中间数大,说明在中间数到结尾的数中,如果小于,则说明在开始和中间数之间,经过多次相同操作,就可以得到我们想查找的数
时间复杂度
时间复杂度就是 O(logn)
代码实现
- 非递归的实现
const testArr = []
let i = 0
while (i < 10000) {
testArr.push(i)
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(arr, n, value) {
let low = 0
let hight = n - 1
let num = 0
while (low <= hight) {
num++
console.log(num)
let mid = parseInt((low + hight) / 2)
if (arr[mid] === value) {
return mid
} else if (arr[mid] < value) {
low = mid + 1
} else {
hight = mid - 1
}
}
return -1
}
- 递归实现
const testArr = []
let i = 0
while (i < 10000) {
testArr.push(i)
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(arr, n, value) {
return bsearchInternally(arr, 0, n - 1, value)
}
function bsearchInternally(a, low, hight, value) {
if (low > hight) {
return -1
}
let mid = parseInt((low + hight) / 2)
if (a[mid] === value) {
return mid
} else if (a[mid] < value) {
return bsearchInternally(a, mid + 1, hight, value)
} else {
return bsearchInternally(a, 0, hight - 1, value)
}
}
二分查找应用场景的局限性
- 二分查找依赖的是顺序表结构,简单点说就是数组。
- 二分查找针对的是有序数据
- 数据量太小不适合二分查找
- 数据量太大也不适合二分查找 (数组需要连续的存储空间,太大的数据需要开辟很大的内存)
变形问题
1. 查找第一个等于给定值的元素
2. 查找最后一个等于给定值的元素
3. 查找第一个大于等于给定值的元素
4. 查找最后一个小于等于给定值的元素
- 查找第一个等于给定值的元素
const testArr = []
let i = 0
while (i < 10000) {
if (i === 5554) {
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
} else {
testArr.push(i)
}
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(a, n, value) {
let low = 0;
let high = n - 1;
while (low <= high) {
let mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
// 等于的时候再做一次处理
if ((mid == 0) || (a[mid - 1] != value)) return mid;
else high = mid - 1;
}
}
return -1;
}
- 查找最后一个等于给定值的元素
const testArr = []
let i = 0
while (i < 10000) {
if (i === 5554) {
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
} else {
testArr.push(i)
}
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(a, n, value) {
let low = 0;
let high = n - 1;
while (low <= high) {
let mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
// 等于的时候再做一次处理
if ((mid == n - 1) || (a[mid + 1] != value)) {
return mid;
} else {
low = mid + 1;
}
}
}
return -1;
}
- 查找第一个大于等于给定值的元素
const testArr = []
let i = 0
while (i < 10000) {
if (i === 5554) {
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
} else {
testArr.push(i)
}
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(a, n, value) {
let low = 0;
let high = n - 1;
while (low <= high) {
let mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
if ((mid == 0) || (a[mid - 1] < value)) return mid; else high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
- 查找最后一个小于等于给定值的元素
const testArr = []
let i = 0
while (i < 10000) {
if (i === 5554) {
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
testArr.push(i)
} else {
testArr.push(i)
}
i++
}
console.log(testArr)
let a = bsearch(testArr, testArr.length, 5554)
console.log(a)
function bsearch(a, n, value) {
let low = 0;
let high = n - 1;
while (low <= high) {
let mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else {
if ((mid == n - 1) || (a[mid + 1] > value)) return mid; else low = mid + 1;
}
}
return -1;
}