二叉树我的爱

在这里插入图片描述

二叉树层次遍历(leetcode102)

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

/**
 * 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) {
    if(!root){
        return [];
    }
    let result = [];
    helper(root,0,result);
    return result;
}

var helper = function(node,level,result){
    if(!node){
        return;
    }
    if(!result[level]){
        result[level]=[node.val]
    }else{
        result[level].push(node.val)
    }
    helper(node.left,level+1,result);
    helper(node.right,level+1,result);
}
// 队列
// var levelOrder = function(root) {
//     if(!root){
//         return []
//     }
//     let queue = [root];
//     let result = [];
//     let level = 0;
//     while(queue.length !== 0){
//         let len = queue.length;
//         for(let i=0;i<len;i++){
//             let node = queue.shift();
//             if(!result[level]){
//                 result[level]=[node.val]
//             }else{
//                 result[level].push(node.val)
//             }
//             if(node.left)queue.push(node.left);
//             if(node.right)queue.push(node.right);
//         }
//         level++;
//     }
//     return result
// };

二叉树前序遍历(leetcode144)

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
 // 非递归解法-栈
var preorderTraversal = function(root) {
    if(!root){
        return [];
    }
    let stack = [root];
    let result = [];
    while(stack.length){
        let node = stack.pop();
        result.push(node.val);
        
        if(node.right){
            stack.push(node.right);
        }
        if(node.left){
            stack.push(node.left);
        }
        
    }
    return result;
};

二叉树后序遍历(leetcode145)

//非递归实现
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    if(!root){
        return [];
    }
    let result = [];
    let stack = [root];
    while(stack.length){
        let node = stack.pop();
        result.unshift(node.val);
        if(node.left){
            stack.push(node.left);
        }
        if(node.right){
            stack.push(node.right);
        }
    }
    return result;
};
//递归实现
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    if(!root){
        return [];
    }
    let result = [];
    traverse(root,result);
    return result;
};

var traverse = function(node, result){
    if(node.left){
        traverse(node.left, result);
    }
    if(node.right){
        traverse(node.right, result);
    }
    result.push(node.val);
    return;
}

二叉树中序遍历(leetcode94)

非递归解法

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    if(!root){
        return [];
    }
    let stack = [];
    let result = [];
    let curr = root;
    while(stack.length || curr!==null ){
    	// 把左子节点都入栈
        while(curr !== null){
            stack.push(curr);
            curr = curr.left;
        }
        // 弹出最左的节点
        let top = stack.pop();
        result.push(top.val);
        // 如果有右子树,遍历右子树
        curr = top.right;
    }
    return result;
};

二叉树路径总和(leetcode113)

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} sum
 * @return {number[][]}
 */
//递归解法
var pathSum = function(root, sum) {
    var result = [];
    var traverse = function(node,total,arr){
        if(!node){
            return;
        }
        let path = [...arr,node.val];
        if(node.left===null&&node.right===null&&total+node.val===sum)        {
            result.push(path);
            return;
        }
        traverse(node.left,total+node.val,path);
        traverse(node.right,total+node.val,path);
    }
    traverse(root,0,[]);
    return result;
};
//栈解法
var hasPathSum = function(root, sum) {
    let stack = [];
    let result = false;
    if(root){
        stack.push([root,sum])
    }
    while(stack.length){
        let item = stack.pop();
        let node = item[0],remain = item[1];
        if(node.left===null && node.right===null && remain-node.val===0){
            result = true;
            break;
        }
        if(node.left){
            stack.push([node.left,remain-node.val]);
        }
        if(node.right){
            stack.push([node.right,remain-node.val]);
        }
    }
    return result;
};

二叉树Z字型遍历(leetcode103)

//队列方法
var zigzagLevelOrder = function(root) {
    
    let queue = [];
    let result = [];

    if(root){
        queue.push([root,0]);
    }
    while(queue.length){
        let item = queue.shift();
        let node = item[0],level=item[1];
        if(result[level]){
            if(level % 2 === 0){
                result[level].push(node.val);
            }else{
                result[level].unshift(node.val);
            }
        }else{
            result[level] = [node.val];
        }

        if(node.left){queue.push([node.left,level+1]);}
        if(node.right){queue.push([node.right,level+1]);}
        
    }
    return result;
};

从前序和中序遍历构造二叉树(leetcode105)

/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    var traverse = function(preorder, inorder){
        if(!preorder.length || !inorder.length){
            return null;
        }
        let t = preorder[0];
        let node = new TreeNode(t);
        let midIndex = inorder.indexOf(t);
        node.left = traverse(preorder.slice(1,midIndex+1),inorder.slice(0,midIndex));
        node.right = traverse(preorder.slice(midIndex+1),inorder.slice(midIndex+1));
        return node;
    }
    return traverse(preorder,inorder);
};

有序链表转换二叉搜索树(LeetCode 109)

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {TreeNode}
 */
var sortedListToBST = function(head) {
    return createTree(head);
};
// 双指针解法
var createTree = function(head){
    // console.log(1,head);
    if(!head)return null;
    if(!head.next){
        return new TreeNode(head.val);
    }
    // p1指向中间节点的前一个节点,p2指向尾结点
    let p1 = head,p2 = head;
    let start = false;
    while(p2.next && p2.next.next){
        p2 = p2.next.next;
        if(!start){
            start = true;
            continue;
        }else{
            p1 = p1.next;
        }
    }
    // console.log('p1',p1);
    // console.log("=====")
    let node = new TreeNode(p1.next.val);
    let newH = p1.next;
    p1.next=null;
    node.left = head?createTree(head):null;
    node.right = newH.next?createTree(newH.next):null;
    return node;
}

判断二叉搜索树是否合理(leetcode98)

中序遍历递归解法

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isValidBST = function(root) {
    if(!root){
        return true;
    }
    let result = true;
    let preValue = null;
    var traverse = function(node){
        if(node.left&&result){
            traverse(node.left);
        }
        if(preValue!==null){
            if(preValue>=node.val)result = false;
        }
        preValue = node.val;
        if(node.right&&result){
            traverse(node.right);
        }
    }
    traverse(root)
    return result;
};

官方解法
左右两个子树都是BST这个树才是BST,当前节点要满足在(lower,upper)区间内

var isValidBST = function(root) {
    if(!root){
        return true;
    }
    return helper(root,-Infinity,Infinity);
};

var helper = function(node,lower,upper){
    if(!node)return true;
    if(node.val<=lower || node.val>=upper){
        return false;
    }
    return helper(node.left,lower,node.val) && helper(node.right,node.val,upper)
}

二叉搜索树中第K小的元素

一般BST遍历==》中序遍历

/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function(root, k) {
    let stack = [];
    let curr = root;
    let count = 0;
    let result = null;
    while(stack.length || curr!==null){
        while(curr!==null){
            stack.push(curr);
            curr = curr.left;
        }

        let top = stack.pop();
        count++;
        if(count === k){
            result = top.val;
            break;
        }
        curr = top.right;
    }
    return result;
};

二叉树两个节点最近祖先(leetcode236)

//参考大佬的做法
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    //递归终止条件:节点为空,节点等于p或q
    if(!root || root === p || root === q)return root;
    //遍历左右子树
    let left = lowestCommonAncestor(root.left,p,q);
    let right = lowestCommonAncestor(root.right,p,q);
    //如果p和q在不同的子树,返回当前节点
    if(left && right) return root;
    //如果p和q在同一个子树,返回那个子树的节点
    return left?left:right;
};

全排列

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
DFS+回溯算法

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function(nums) {
    let result = [];
    let len = nums.length;
    if(!len){
        return [];
    }
    let path = [];
    let used = [];
    dfs(nums,len,0,path,used,result);
    return result
};

var dfs = function(nums,len,depth,path,used,result){
    if(depth === len){
        result.push(path.slice());
        return;
    }
    for(let i=0;i<len;i++){
        if(used[i]){
            continue;
        }
        path.push(nums[i]);
        used[i] = true;
        dfs(nums,len,depth+1,path,used,result);
        path.pop();
        used[i] = false;
    }
}

反转链表

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
// 递归解法
var reverseList = function(head) {
    if(!head)return null;
    if(head.next === null)return head;
    let last = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return last;
};

// 迭代解法
var reverseList = function(head) {
    if(!head)return null;
    let pre = head, curr = head.next, newHead=head;
    while(curr!==null){
        newHead = curr;
        curr = curr.next;
        newHead.next = pre;
        if(pre===head)pre.next = null;
        pre = newHead;
    }
    return newHead;
};

对称二叉树(LeetCode101)

对称二叉树

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
 // 非递归解法
var isSymmetric = function(root) {
    if(!root)return true;
    let queue = [root.left,root.right];
    while(queue.length!==0){
        let v1 = queue.shift();
        let v2 = queue.shift();
        if(v1 === null && v2 === null){
            continue;
        }
        if(v1 ===null || v2===null){
            return false;
        }
        if(v1.val !== v2.val){
            return false;
        }
        queue.push(v1.left);
        queue.push(v2.right);
        queue.push(v1.right);
        queue.push(v2.left);
    }
    return true;
};
// 递归解法
// var isSymmetric = function(root) {
//     if(!root)return true;
//     return isMirror(root.left,root.right)
// };

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

平衡二叉树(LeetCode110)

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
 // 递归解法
var isBalanced = function(root) {
    if(!root)return -1;
    return Math.abs(depth(root.left)-depth(root.right))<2 && isBalanced(root.left) && isBalanced(root.right);
};

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

二叉树的最小深度(LeetCode 111)

/**
* 递归解法
* 当前节点的最小深度 = 左右子节点最小深度+1
*/
var minDepth = function(root){
    if(!root)return 0;
    if(root.left === null && root.right === null){
        return 1;
    }
    let min = Infinity;
    if(root.left)min = Math.min(minDepth(root.left),min);
    if(root.right)min = Math.min(minDepth(root.right),min);
    return min+1;
}

/**
* 层次遍历 遇到的第一个叶子节点所在深度就是最小深度
*/
var minDepth = function(root) {
    if(!root)return 0;
    let queue = [root];
    let level = 1;
    while(queue.length){
        let len = queue.length;
        for(let i = 0;i<len;i++){
            let node = queue.shift();
            if(node.left === null && node.right === null){
                return level;
            }
            if(node.left)queue.push(node.left);
            if(node.right)queue.push(node.right);
        }
        level++;
    }
};

二叉树路径总和(LeetCode 112)

给定二叉树和目标值,是否存在一条路径和为目标值

/**
 * @param {TreeNode} root
 * @param {number} sum
 * @return {boolean}
 */
 /**
  * 栈解法
  * 栈里存储节点和剩余的值
  */
var hasPathSum = function(root, sum) {
    let stack = [];
    let result = false;
    if(root){
        stack.push([root,sum])
    }
    while(stack.length){
        let item = stack.pop();
        let node = item[0],remain = item[1];
        if(node.left===null && node.right===null && remain-node.val===0){
            result = true;
            break;
        }
        if(node.left){
            stack.push([node.left,remain-node.val]);
        }
        if(node.right){
            stack.push([node.right,remain-node.val]);
        }
    }
    return result;
};
 /**
  * 递归解法
  */
var hasPathSum = function(root, sum) {
    return trans(root,0,sum);
};

var trans = function(node, total, sum){
    if(!node){
        return false;
    }
    if(node.left===null&&node.right===null){
        return total + node.val === sum;
    }

    return trans(node.left, total+node.val, sum) || trans(node.right, total+node.val, sum);
    
}

旋转数组(LeetCode 189)

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
思路:
[1,2,3,4,5,6,7]
[7,6,5,4,3,2,1] 反转数组
[5,6,7|1,2,3,4] 从第k个位置两边分别反转

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var rotate = function(nums, k) {
    let len = nums.length;
    let forward = k % len;

    reverse(nums,0,len-1);
    reverse(nums,0,forward-1);
    reverse(nums,forward,len-1);
};

var reverse = function(nums,start,end){
    while(start<end){
        let temp = nums[start];
        nums[start]=nums[end];
        nums[end] = temp;
        start++;
        end--;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值