关于搜索的那些事

前言


二分搜索

  1. 非递归实现
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
}

  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
在这里插入图片描述

深度遍历

  1. 递归实现
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
}
  1. 非递归实现
// 非递归实现深度优先搜索
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
}

广度遍历

  1. 非递归实现
// 非递归实现广度优先遍历
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))
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值