前端力扣刷题_数据结构篇(树)

二叉树的遍历方式

前序遍历、中序遍历、后序遍历都属于DFS(深度优先遍历),往往用递归实现。
递归就是思考这个函数的功能是什么!一定注意要有递归终止条件!(1,定义终止条件;2,实现功能;3,调用递归。23顺序不一定)

## 二叉树的前序遍历:
此函数的功能就是给一个根节点,返回一个此节点的前序遍历数组。前序遍历的顺序是(中左右):[root,(传入左子树根结点,返回)左子树的前序遍历,(传入右子树根结点,返回)右子树的前序遍历]

var preorderTraversal = function(root) {
    if(root===null) return [];
    const res=[];
    res.push(root.val);
    if(root.left) res.push(...preorderTraversal(root.left));
    if(root.right) res.push(...preorderTraversal(root.right));
    return res;
};

## 二叉树的中序遍历

左中右:[(传入左子树根结点,返回)左子树的中序遍历,root,(传入右子树根结点,返回)右子树的中序遍历]

var inorderTraversal = function(root) {
    if(root===null) return [];
    const res=[];
    res.push(...inorderTraversal(root.left));
    res.push(root.val);
    res.push(...inorderTraversal(root.right));
    return res;
};

## 二叉树的后序遍历:

左右中:[(传入左子树根结点,返回)左子树的后序遍历,(传入右子树根结点,返回)右子树的后序遍历,root]

var postorderTraversal = function(root) {
    if(root===null) return [];
    const res=[];
    res.push(...postorderTraversal(root.left));
    res.push(...postorderTraversal(root.right));
    res.push(root.val);
    return res;
};

## 二叉树的层序遍历
属于BFS(广度优先搜索),往往用队列实现。
①(Medium版)

var levelOrder = function(root) {
    if(root===null) return [];
    const queue=[];
    const res=[];
    queue.push(root);
    while(queue.length!==0){
        let levelSize=queue.length;
        res.push([]);
        for(let i=0;i<levelSize;i++){
            let node=queue.shift();
            res[res.length-1].push(node.val);
            if(node.left!==null){
                queue.push(node.left);
            }
            if(node.right!==null){
                queue.push(node.right);
            }
        }
    }
    return res;
};

②从上到下打印二叉树(简单版),要求返回一个数组就可,不用分层。

var levelOrder = function(root) {
    if(root===null) return [];
    const queue=[];
    const res=[];
    queue.push(root);
    while(queue.length!==0){
        let node=queue.shift();
        res.push(node.val);
        if(node.left!==null){
            queue.push(node.left);
        }
        if(node.right!==null){
            queue.push(node.right);
        }
    }
    return res;
};

medium版while里四行是要进for循环的且在while下面for循环前面多了两行。
二叉树的锯齿形层次遍历

var zigzagLevelOrder = function(root) {
    if(root===null) return [];
    const res=[];
    const queue=[];
    queue.push(root);
    let isOdd=true;
    while(queue.length!==0){
        let levelSize=queue.length;
        res.push([]);
        for(let i=0;i<levelSize;i++){
            let node=queue.shift();
            if(isOdd){
                res[res.length-1].push(node.val);
            }else{
                res[res.length-1].unshift(node.val);
            }         
            if(node.left) queue.push(node.left);
            if(node.right) queue.push(node.right);
        }
    //!isOdd&&res[res.length-1].reverse();
    isOdd=!isOdd;
    }
    return res;
};

二叉树的右视图

var rightSideView = function(root) {
    if (root===null) return [];
    const queue = [];
    const res = [];
    queue.push(root);
    while(queue.length!==0){
        res.push([]);
        let levelSize=queue.length;
        for(let i=0;i<levelSize;i++){
            let node=queue.shift();
            res[res.length-1].push(node.val);
            if(node.left!==null) queue.push(node.left);
            if(node.right!==null) queue.push(node.right);
        }
    }
    const result=[];
    for(let i=0;i<res.length;i++){
        result.push(res[i][res[i].length-1]);
    }
    return result;
};

递归的题:

二叉树的最小深度

var minDepth = function(root) {
    if(root===null) return 0;
    if(root.left===null) return minDepth(root.right)+1;//比二叉树的最大深度多了判断左右结点存不存在的一步
    if(root.right===null) return minDepth(root.left)+1;//
    return Math.min(minDepth(root.left),minDepth(root.right))+1;
};

二叉树的最大深度:

var maxDepth = function(root) {
    if(root===null) return 0;
    return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
};

二叉树的直径!!!!!!!!!!!!!!!!!!
深度是结点的个数,直径是所有结点间边的个数(也等于左结点数+右结点数)。

var diameterOfBinaryTree = function(root) {
    let ans=0;
    function maxDepth(root){
        if(root===null) return 0;
        let leftDepth=maxDepth(root.left);
        let rightDepth=maxDepth(root.right);
        ans=Math.max(ans,leftDepth+rightDepth);
        return Math.max(leftDepth,rightDepth)+1;
    }
    maxDepth(root);
    return ans;
};

判断是不是平衡二叉树与二叉树的最大深度有关系
平衡二叉树:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1

var isBalanced = function(root) {
    if(root===null) return true;
    let leftDepth=maxDepth(root.left);
    let rightDepth=maxDepth(root.right);
    return Math.abs(leftDepth-rightDepth)<=1&&isBalanced(root.left)&&isBalanced(root.right);
};
var maxDepth=function(pRoot){
    if(pRoot===null) return 0;
    return Math.max(maxDepth(pRoot.left),maxDepth(pRoot.right))+1; 
}

重建二叉树(从前序和中序遍历序列构造二叉树)
前端力扣刷题_数据结构篇(树)_第1张图片

var buildTree = function(preorder, inorder) {
    if(preorder.length===0||inorder.length===0){return null;}
    const root =new TreeNode(preorder[0]);//创建根结点
    const target=preorder[0];//取出根结点的值
    const rootIndex=inorder.indexOf(target);
    let leftIn=inorder.slice(0,rootIndex);//左中
    let rightIn=inorder.slice(rootIndex+1);//右中
    let leftPre=preorder.slice(1,rootIndex+1);//左前
    let rightPre=preorder.slice(rootIndex+1);//右前
    root.left=buildTree(leftPre,leftIn);
    root.right=buildTree(rightPre,rightIn);
    return root;
};

二叉树的镜像(翻转二叉树)

function Mirror( pRoot ) {
    if(pRoot===null){
        return null;
    }
    [pRoot.left,pRoot.right]=[pRoot.right,pRoot.left];//解构赋值,实现二叉树根结点下面俩子结点反转
    Mirror(pRoot.left);//递归调用Mirror函数实现将以pRoot为根节点的树反转
    Mirror(pRoot.right);//递归调用Mirror函数实现将以pRoot为根节点的树反转
    return pRoot;
}

对称的二叉树

var isSymmetric = function(root) {
    if(root===null) return true;
    return compareRoots(root.left,root.right);
};
var compareRoots=function(leftRoot,rightRoot){
    if(leftRoot===null){
        if(rightRoot===null){
            return true;
        }else{
            return false;
        }
    }
    if(rightRoot===null){
        return false;
    }
    if(leftRoot.val!==rightRoot.val){
        return false;
    }
    return compareRoots(leftRoot.left,rightRoot.right)&&compareRoots(leftRoot.right,rightRoot.left);
}

相同的树

var isSameTree = function(p, q) {
    if(p===null&&q===null) return true;
    if((p===null&&q!==null)||(p!==null&&q===null)) return false;
    if(p.val===q.val){return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right)}
    else if(p.val!==q.val){return false;}
};

求根结点到叶子结点数字之和!!!

var sumNumbers = function(root) {
    return dfs(root,0);
};
const dfs=(root,prevSum)=>{
    if(root===null) return 0;
    const sum=prevSum*10+root.val;
    if(root.left===null&&root.right===null){
        return sum;
    }else{
        return dfs(root.left,sum)+dfs(root.right,sum);
    }
}  

二叉树中和为某一值的路径(easy版)
属于先序遍历

function hasPathSum( root ,  sum ) {
    if(root===null) return false;
    if(root.val===sum&&root.left===null&&root.right===null){return true;}
    return (hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val));
}

树的子结构
思路:子树B的根结点可能为A树的任意一个根结点nA,所以一:要先序遍历A树(因为先序遍历是中优先);二:判断以nA为根结点的子树是否包含B(另写函数实现)。
递归要注意终止条件:

在这里插入代码片

二叉搜索树的第k大结点
二叉搜索树:根结点左侧节点如果存在,值都小于根结点,右侧节点如果存在,值都大于根结点。
中序遍历:左根右
利用性质:二叉搜索树的中序遍历是递增序列

var kthLargest = function(root, k) {
    let res=inorderTraversal(root);
    return res[res.length-k];
};
var inorderTraversal=function(root){
    if(root===null) return [];
    const res=[];
    if(root.left){
        res.push(...inorderTraversal(root.left));
    }
    res.push(root.val);
    if(root.right){
        res.push(...inorderTraversal(root.right));
    }
    return res;
}

二叉搜索树中的搜索

var searchBST = function(root, val) {
    if(root===null) return null;
    if(root.val===val) return root;
    return searchBST(root.val<val?root.right:root.left,val);
};

验证二叉搜索树
先中序遍历再查看是否是严格递增序列

var isValidBST = function(root) {
    const inOrder=(root)=>{
        if(root===null) return [];
        const res=[];
        if(root.left!==null) res.push(...inOrder(root.left));
        res.push(root.val);
        if(root.right!==null) res.push(...inOrder(root.right));
        return res;
    }
    const arr=inOrder(root);
    for(let i=1;i<arr.length;i++){
        if(arr[i-1]>=arr[i]){
            return false;
        }
    }
    return true;
};

不同的二叉搜索树规律题,死记硬背公式

var numTrees = function(n) {
    let C = 1;
    for (let i = 0; i < n; ++i) {
        C = C * 2 * (2 * i + 1) / (i + 2);
    }
    return C;
};

二叉树展开为链表先进行前序遍历

var flatten = function(root) {
    const preOrder=(root)=>{
        if(root===null) return [];
        const res=[];
        res.push(root);//这里是push(root)而不是push(root.val)
        if(root.left!==null) res.push(...preOrder(root.left));
        if(root.right!==null) res.push(...preOrder(root.right));
        return res;
    }
    let arr=preOrder(root);
    for(let i=1;i<arr.length;i++){
        const pre=arr[i-1],cur=arr[i];
        pre.left=null;
        pre.right=cur;
    }
};

合并二叉树

var mergeTrees = function(root1, root2) {
    if(root1===null) return root2;
    if(root2===null) return root1;
    root1.val=root1.val+root2.val;
    root1.left=mergeTrees(root1.left,root2.left);
    root1.right=mergeTrees(root1.right,root2.right);
    return root1;
};

二叉树的最近公共祖先!!!!!!!!!!!!!!!

const lowestCommonAncestor = (root, p, q) => {
    if (!root) return null;
    // 根节点等于p或q,那么root是最近公共祖先
    if (root === p || root === q) return root;
    // 向左子树寻找节点相同的点
    const left = lowestCommonAncestor(root.left, p, q);
    // 向右子树寻找节点相同的点
    const right = lowestCommonAncestor(root.right, p, q);
    // 若左右各找到一个,那么当前根节点就是最近公共祖先
    if (left && right) return root;
    // 只有左边找到,那么最近公共祖先在左边
    if (left) return left;
    // 只有右边找到,那么最近公共祖先在右边
    if (right) return right;
};

你可能感兴趣的:(前端,leetcode,数据结构,算法)