【js】-【DFS、BFS应用】-学习笔记

28 篇文章 0 订阅
14 篇文章 0 订阅

1 二叉树的遍历-递归-DFS

// 所有遍历函数的入参都是树的根结点对象
function preorder(root) {
    // 递归边界,root 为空
    if(!root) {
        return 
    }
     
    // 输出当前遍历的结点值
    console.log('当前遍历的结点值是:', root.val)  
    // 递归遍历左子树 
    preorder(root.left)  
    // 递归遍历右子树  
    preorder(root.right)
}

2 二叉树的层序遍历-BFS

function BFS(root) {
    const queue = [] // 初始化队列queue
    // 根结点首先入队
    queue.push(root)
    // 队列不为空,说明没有遍历完全
    while(queue.length) {
        const top = queue[0] // 取出队头元素  
        // 访问 top
        console.log(top.val)
        // 如果左子树存在,左子树入队
        if(top.left) {
            queue.push(top.left)
        }
        // 如果右子树存在,右子树入队
        if(top.right) {
            queue.push(top.right)
        }
        queue.shift() // 访问完毕,队头元素出队
    }
}
BFS(root) //执行BFS

3 给定一个没有重复数字的序列,返回其所有可能的全排列

https://mp.csdn.net/mp_blog/creation/success/124684440
在这里插入图片描述

示例:   
输入: [1,2,3]
输出: [
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
// 入参是一个数组
const permute = function(nums) {
  // 缓存数组的长度
  const len = nums.length
  // curr 变量用来记录当前的排列内容
  const curr = []
  // res 用来记录所有的排列顺序
  const res = []
  // visited 用来避免重复使用同一个数字
  const visited = {}
  // 定义 dfs 函数,入参是坑位的索引(从 0 计数)
  function dfs(nth) {
  
      # 若遍历到了不存在的坑位(第 len+1 个),则触碰递归边界返回
      if(nth === len) {
          // 此时前 len 个坑位已经填满,将对应的排列记录下来
          res.push(curr.slice())
          return 
      }
      // 检查手里剩下的数字有哪些
      for(let i=0;i<len;i++) {
          // 若 nums[i] 之前没被其它坑位用过,则可以理解为“这个数字剩下了”
          if(!visited[nums[i]]) {
              # 给 nums[i] 打个“已用过”的标
              visited[nums[i]] = 1
              // 将nums[i]推入当前排列
              curr.push(nums[i])
              // 基于这个排列继续往下一个坑走去
              dfs(nth+1) 
              // nums[i]让出当前坑位
              curr.pop()
              // 下掉“已用过”标识
              visited[nums[i]] = 0
          }
      }
  }
  # 从索引为 0 的坑位(也就是第一个坑位)开始 dfs
  dfs(0)
  return res
};

res.push(curr.slice()) 而不是简单的 res.push(curr) 。为什么这样做?因为全局只有一个唯一的 currcurr 的值会随着 dfs 的进行而不断被更新。 slice 方法的作用是帮助我们拷贝出一个不影响curr正本的副本,以防直接修改到curr的引用。

4 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集

https://mp.csdn.net/mp_blog/creation/success/124684440

示例: 输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
// 入参是一个数组
const subsets = function(nums) {
    // 初始化结果数组
    const res = []   
    // 缓存数组长度
    const len = nums.length
    // 初始化组合数组
    const subset = []
    // 进入 dfs
    dfs(0)  

    // 定义 dfs 函数,入参是 nums 中的数字索引
    function dfs(index) {
        // 每次进入,都意味着组合内容更新了一次,故直接推入结果数组
        res.push(subset.slice())
        
        # 从当前数字的索引开始,遍历 nums
        for(let i=index;i<len;i++) {
            // 这是当前数字存在于组合中的情况
            subset.push(nums[i]) 
            // 基于当前数字存在于组合中的情况,进一步 dfs
            dfs(i+1)
            // 这是当前数字不存在与组合中的情况
            subset.pop()
        }
    }
    // 返回结果数组
    return res 
};
function allSubsets(arr){
	let res = [[]];
	for(let i = 0; i < arr.length; i++){
		const tempRes = res.map(subset => {
			const one = subset.concat([]);
			one.push(arr[i]);
			return one;
		})
		res = res.concat(tempRes);
	}
	return res;
}

5 给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合

示例: 输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
const combine = function(n, k) {
   // 初始化结果数组
    const res = []   
    // 初始化组合数组
    const subset = []
    // 进入 dfs,起始数字是1
    dfs(1)  

    # 定义 dfs 函数,入参是当前遍历到的数字
    function dfs(index) {
        if(subset.length === k) {
            res.push(subset.slice())
            return 
        }
        # 从当前数字的值开始,遍历 index-n 之间的所有数字
        for(let i=index;i<=n;i++) {
            // 这是当前数字存在于组合中的情况
            subset.push(i) 
            // 基于当前数字存在于组合中的情况,进一步 dfs
            dfs(i+1)
            // 这是当前数字不存在与组合中的情况
            subset.pop()
        }
    }
    // 返回结果数组
    return res 
};
function xxx(入参) {
  前期的变量定义、缓存等准备工作   
  // 定义路径栈
  const path = []
  // 进入 dfs
  dfs(起点)  
  // 定义 dfs
  dfs(递归参数) {
    if(到达了递归边界) {
      结合题意处理边界逻辑,往往和 path 内容有关
      return   
    }   
    // 注意这里也可能不是 for,视题意决定
    for(遍历坑位的可选值) {
      path.push(当前选中值)
      处理坑位本身的相关逻辑
      path.pop()
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值