Leetcode之二叉树模块记录(一)

树的遍历

树的前序遍历

在这里插入图片描述

  1. 迭代实现
var preorderTraversal = function(root) {
	let list = [];
	let result = [];
	if (!root) return result;
	list.push({
		color:'white',
		node:root
	})
	while (list.length > 0) {
		let temp = list.pop(); // 取出list中最后一个节点;
		let {color,node} = temp;
		// white表示该节点的左右子树还没有被添加进list存储
		if (color === 'gary') {
			result.push(node.val);
		} else {
		// 前序遍历的顺序为根节点-> 左子树 -> 右子树,因为每一次都是取出最后一个元素,
		// 而push方法没次都将元素追加到最后面,所以最先出list的应该最后加入
			node.right && list.push({color:'white',node:node.right});
			node.left && list.push({color:'white',ndoe:node.left});
			list.push({color:'gray',node})
		}
	}
}
  1. 递归实现
var preorderTraversal = function(root) {
	if (root) {
		return [root.val,...preorderTraversal(root.left),...preorderTraversal(root.right)]
	} else {
	return []
	}
}
树的中序遍历

在这里插入图片描述

  1. 迭代实现
var inorderTraversal = function(root) {
    let list = [];
    let result = [];
    if(!root) return result;
    list.push({
        color:"white",
        node:root
    })
    while(list.length > 0){
        let {color,node} = list.pop();
        if(color === "gray"){
            result.push(node.val)
        }else{
        // 与上面原理相同
            node.right && list.push({color:"white",node:node.right});
            list.push({color:"gray",node})
            node.left && list.push({color:"white",node:node.left});
        }
    }
    return result;

};
  1. 递归实现
var inorderTraversal = function(root) {
    if(root) {
        return [...inorderTraversal(root.left),root.val,...inorderTraversal(root.right)]
    }
    else{
        return []
    }
 }
后续遍历

在这里插入图片描述

  1. 迭代实现
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var postorderTraversal = function(root) {
    let result = [];
    let stack = [];
    if(!root) return result;
    stack.push({
        color:"white",
        node:root
    });
    while(stack.length > 0) {
        let {color,node} = stack.pop();
        if(color === "gray"){
            result.push(node.val);
        }else{
            stack.push({color:"gray",node});
            node.right && stack.push({color:"white",node:node.right});
            node.left && stack.push({color:"white",node:node.left});
        }
    }
    return result;

};
  1. 递归实现
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var postorderTraversal = function(root) {
    递归实现
    if(root){
        return [...postorderTraversal(root.left),...postorderTraversal(root.right),root.val]
    }else{
        return []
    }
 } 
层序遍历

在这里插入图片描述思路:实际上就是对广度优先遍历的一个变型,需要加一个size来记录每一层值的数量,并且将每一层放置在一个数组里加以保存。

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
	let order = [];
	let result = [];
	if (!root) return [];
	order.push(root);
	while(order.length > 0) {
		let item = [];
		let size = order.length;
		// 将该层的每一个节点的左右孩子放置在order中,将该层的所有节点放置在item中,放完后添加至result中
		while(size > 0) {
			let node = order.shift();
			item.push(node.val);
			node.left && order.push(node.left);
			node.right && order.push(node.right);
			size--;
		}
		result.push(item);
	}
	return result;
}

根据遍历的结果构造二叉树

根据中序遍历与后序遍历构造二叉树

思路:构造二叉树主要有以下步骤:
① 找到根节点来分割左子树和右子树。
② 使用递归的思维求得根节点。
从后续遍历中,可以得知后续遍历数组中最后一个节点就是根节点,得到根节点后从中序遍历中查找根节点的位置,根节点位置之前为左子树,根节点位置之后为右子树。
还有另一个技巧是“两种遍历中,同一子树的节点数目是相同的”,如:
中序遍历中,我们知道 左子树:[inorder_start,index-1], 右子树:[index+1, inorder_end]
在后序遍历中,左子树起始位置为post_start,左子树一共有(index-1 - inorder_start + 1)个,因此左子树:[post_start, post_start + (index-1 - inorder_start)],后面的均为右子树和根节点部分且右子树的终止位置为post_end - 1。
实现代码如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} inorder
 * @param {number[]} postorder
 * @return {TreeNode}
 */
var buildTree = function(inorder, postorder) {
    if (!postorder.length) return null;
    const top = postorder.pop();
    const root = new TreeNode(top);
    const topIndex = inorder.indexOf(top);
    root.left = buildTree(inorder.slice(0, topIndex), postorder.slice(0, topIndex));
    root.right = buildTree(inorder.slice(topIndex + 1), postorder.slice(topIndex));
    return root;
};
根据前序遍历与中序遍历构造二叉树

思路:① 根据前序遍历,我们知道前序遍历列表中第一个元素就是根节点,将根节点的值去中序列表中查找,知道根节点在中序列表中的位置,那么中序列表中该位置之前的节点为左子树,该位置之后的节点为右子树。
② 从而我们可以得知该二叉树中的左右子树节点的个数,设左子树的节点数量为x。前序列表中从第二个节点开始为左子树的根节点,然后再往右数x-1个位置即可,后面的均为右子树的节点。
代码如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    if(!preorder.length) return null;
    const root = new TreeNode(preorder[0]);
    let index = inorder.indexOf(root.val);
    root.left = buildTree(preorder.slice(1,index + 1),inorder.slice(0,index));
    root.right = buildTree(preorder.slice(index + 1),inorder.slice(index + 1))
    return root;

};
根据前序遍历与后序遍历构造二叉树

思路:
① 首先我们可以显然知道当前根节点为pre[pre_start],并且它在后序中的位置为post_end,因此这里我们需要找到能区分左右子树的节点。
我们知道左子树的根节点为pre[pre_start+1],因此只要找到它在后序中的位置就可以分开左右子树(index的含义)
② 后序遍历中,我们知道 左子树:[post_start,index], 右子树:[index+1, post_end-1]在前序遍历中,左子树起始位置为pre_start+1,左子树个数一共有(index - post_start)个,因此左子树:[pre_start+1, pre_start+1 + (index - post_start)]
右子树起始位置为左子树终止位置+1,终止位置为pre_end,因此右子树:[ pre_start+1 + (index - post_start) + 1, pre_end]
代码实现如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, postorder) {
	if(!preorder.length) return null;
	let end = postorder.pop();
	let root = new TreeNode(end);
	let index = postorder.indexOf(preorder[1].val);
	root.left = buildTree(preorder.slice(1,index + 1),postorder.slice(0,index));
	root.right = buileTree(preorder.slice(index + 1),postorder.slice(index));
	return root;
	
}

参考:
作者:christmas_wang
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/solution/kan-wo-jiu-gou-liao-san-chong-bian-li-fang-shi-g-2/
来源:力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值