刷题记录

77 阅读3分钟

l--- highlight: a11y-dark

最近在leetcode上刷题,感觉到自己的功力还远远不够,尤其是对二叉树相关问题的求解,很多时候甚至连思路都不清晰,更不用说敲代码了
在刷了几道题后,也算是小有总结:
总体来说,可能是刷题类型的缘故,目前接触到的二叉树相关算法题,都需要使用递归,而通常递归的各种边界条件都十分难思考,可能还需要不断都学习以及总结。
个人认为,之所以二叉树问题求解都会涉及到递归,是因为二叉树与数组类型问题不同,无法通过输入直接判定方法的结束,并且和链表也不相同,无法仅通过一个循环将整个事件流程整理清楚,所以需要递归对不同方向上的链表进行分类讨论,最后获得想要的结果\

附刷题记录:

266.翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
solve:

let reverse = function(root){
    if(!root) return null
    let left = reverse(root.left)
    let right = reverse(root.right)
    root.left = right
    root.right = left
    return root
}

思路:

  1. 判断当前节点是否为空,是则返回null,说明已经走到叶子节点尽头
  2. 向左支递归
  3. 向右只递归
  4. 交换当前节点的左右只
  5. 返回当前节点

剑指 Offer 68 - II. 二叉树的最近公共祖先

solve:

let solve = function(root, p, q){
    if(!root) return null
    if(root.val===p.val||root.val===q.val) return root
    let left = solve(root.left, p, q)
    let right = solve(root.right, p, q)
    if(left&&right) return root
    return left || right
}

思路:

  1. 判断当前节点是否为空,是则返回null,说明已经走到叶子节点尽头
  2. 如果当前节点值为p或q,则返回当前节点
  3. 向左支递归
  4. 向右只递归
  5. 如果当前节点的左右递归结果不为空,说明就是目标节点,则返回当前节点
  6. 返回左递归或右递归结果

206. 反转链表

solve:

let reverse = function(root){
    let pre = null,
    cur = root
    while(cur){
        let nextNode = cur.next
        cur.next = pre
        pre = cur
        cur = nextNode
    }
    return pre
}

思路:

  1. 从第一个节点开始,记录前一节点pre以及后一节点nextNode
  2. 当前节点的下一节点cur.next指向上一节点pre
  3. 将当前节点置为pre,下一节点置为cur
  4. 重复上述操作直至cur为null
  5. 此时pre即为原始链表的结尾,也就是反转后的链表开头
  6. 返回pre

234. 回文链表

solve:

let reverse = function(root){
    let pre = null,
    cur = root
    while(cur){
        let nextNode = cur.next
        cur.next = pre
        pre = cur
        cur = nextNode
    }
    return pre
}
let isPalindrome = function(head){
    let slow = fast = head
    while(fast&&fast.next){
        fast = fast.next.next
        slow = slow.next
    }
    if(fast){
        slow = slow.next
    }
    slow = reverse(slow)
    while(slow){
        if(head.val!==slow.val) return false
        head = head.next
        slow = slow.next
    }
    return true
}

543. 二叉树的直径

solve:

let diameterOfBinaryTree = function(root){
    let ans = 0
    function solve(root){
        if(!root) return 0
        let left = solve(root.left)
        let right = solve(root.right)
        //这里两结点之间的路径长度是以它们之间边的数目表示,所以不需要加1
        ans = Math.max(left + right, ans)
        return Math.max(left, right) + 1
    }
    return ans
}

剑指 Offer 55 - I. 二叉树的深度

solve:

//dfs
let maxDepth = function(root){
    if(!root) return 0
    let left = maxDepth(root.left)
    let right = maxDepth(root.right)
    return Math.max(left, right) + 1
}
//bfs
let maxDepth = function(root){
    if(!root) return 0
    let queue = [root], ans = 0
    while(queue.length){
        let len = queue.length
        while(len){
            let node = queue.shift()
            if(node.left){
                queue.push(node.left)
            }
            if(node.right){
                queue.push(node.right)
            }
            len--
        }
        ans++
    }
    return ans
}