前言
二分搜索
- 非递归实现
function binarySearch (arr, node) {
if (!arr) return
let left = 0, right = arr.length - 1
while (left <= right) {
let mid = Math.floor((left + right) / 2)
if (arr[mid] === node) {
return mid
} else if (arr[mid] < node) {
left = mid + 1
} else if (arr[mid] > node) {
right = mid - 1
}
}
return -1
}
- 递归实现
function binaryRecursionSearch (arr, node, left, right) {
if (!arr) return -1
let mid = Math.floor((left + right) / 2)
if (left > right) return -1
if (arr[mid] === node) return mid
if (arr[mid] < node) {
left = mid + 1
return binaryRecursionSearch(arr, node, left, right)
} else if (arr[mid] > node) {
right = mid - 1
return binaryRecursionSearch(arr, node, left, right)
}
}
二分搜索的使用场景
二分搜索的时间复杂度为O(n)=logN,但必须要求搜索对象为数组且以按照顺序排列。
为什么不能遍历链表呢?
更准确的说法,二分搜索并不适合遍历链表,会增加时间复杂度,根本在于链表在内存中的存储方式。
我们不能保证遍历链表时,在时间复杂度O(1)内获取链表的值。相反每次查询链表平均O(n)=n/2,加上二分搜索的O(n)=logN,时间复杂度将变为O(n)=nlogN
深度遍历
- 递归实现
function dfsTraverse (root, res) {
if (!root) return null
res.push(root)
let childrenList = root.children
for (let i = 0; i < childrenList.length; i++) {
dfsTraverse(childrenList[i], res)
}
return res
}
- 非递归实现
// 非递归实现深度优先搜索
function dfs (root) {
let res = []
if (root) {
let stack = []
stack.push(root)
while (stack.length !== 0) {
let childrenItem = stack.pop()
res.push(childrenItem)
let childrenList = childrenItem.children
for (let i = childrenList.length - 1; i >= 0; i--) {
stack.push(childrenList[i])
}
}
}
return res
}
广度遍历
- 非递归实现
// 非递归实现广度优先遍历
function bfs (root) {
let res = []
if (root) {
let queue = []
queue.unshift(root)
while (queue.length !== 0) {
let childrenItem = queue.shift()
res.push(childrenItem)
let childrenList = childrenItem.children
for (let i = 0; i < childrenList.length; i++) {
queue.unshift(childrenList[i])
}
}
}
return res
}
跳跃游戏③_中等
这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者i - arr[i]。 请你判断自己是否能够跳到对应元素值为 0 的 任意 下标处。 注意,不管是什么情况下,你都无法跳到数组之外。
示例1: 输入:arr = [4,2,3,0,3,1,2], start = 5 输出:true 解释: 到达值为 0 的下标 3有以下可能方案: 下标 5 -> 下标 4 -> 下标 1 -> 下标 3 下标 5 -> 下标 6 -> 下标 4 -> 下标 1-> 下标 3
示例 2: 输入:arr = [4,2,3,0,3,1,2], start = 0 输出:true 解释: 到达值为 0 的下标 3 有以下可能方案: 下标 0 -> 下标 4 -> 下标 1 -> 下标 3 示例 3: 输入:arr = [3,0,2,1,2], start = 2 输出:false 解释:无法到达值为 0 的下标 1 处。
提示: 1 <=arr.length <= 5 * 10^4 0 <= arr[i] < arr.length 0 <= start <
arr.length
/**
* @param {number[]} arr
* @param {number} start
* @return {boolean}
*/
var canReach = function (arr, start) {
let val = arr[start]
if (val === 0) return true
if (val === -1) return false
arr[start] = -1
return (start + val) < arr.length && canReach(arr, (start + val)) || (start - val) >= 0 && canReach(arr, (start - val))
};