【剑指 Offer】第 15 天

132 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、前言

刷题啊!!!

开始刷 “剑指 Offer” 31天。刷完时间:2022.3.6 ~ 2022.3.20。



二、题目

题目:

  • 二叉树中和为某一值的路径
  • 二叉搜索树与双向链表
  • 二叉搜索树的第k大节点

(1)剑指 Offer 34. 二叉树中和为某一值的路径

题目描述


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

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

题解


注意:要从根节点到子节点,才算完整的链路。

思路:

  • 遍历节点的左右子树
  • 更新 target
  • 添加到结果

AC 代码如下:

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        if (null == root) return Collections.emptyList();

        List<List<Integer>> result = new ArrayList<>();
        
        findPath(result, root, Collections.emptyList(), target);

        return result;
    }

    private void findPath(List<List<Integer>> result, TreeNode root, List<Integer> list, int target) {
        if (null == root) return;
        if (root.val == target && null == root.left && null == root.right) {
            List<Integer> subList = new ArrayList<>(list);
            subList.add(root.val);
            result.add(subList);
            return;
        }
        
        List<Integer> tmpList = new ArrayList<>(list);
        tmpList.add(root.val);
        findPath(result, root.left, tmpList, target - root.val);
        tmpList = new ArrayList<>(list);
        tmpList.add(root.val);
        findPath(result, root.right, tmpList, target - root.val);
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode() {}
    TreeNode(int val) { this.val = val; }
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

(2)剑指 Offer 36. 二叉搜索树与双向链表

题目描述


输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

为了让您更好地理解问题,以下面的二叉搜索树为例:

我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。

题解


AC 代码如下:

class Solution {
    public Node treeToDoublyList(Node root) {
        if (null == root) return null;
        Node dummy = new Node(0);
        LinkedList<Node> list = new LinkedList<>();
        travel(list, root);

        Node cur = dummy;
        
        for (Node node : list) {
            
            cur.right = node;
            node.left = cur;
            cur = node;
        }
        
        Node head = list.peekFirst();
        Node tail = list.peekLast();
        
        head.left = tail;
        tail.right = head;

        return head;
    }

    private void travel(LinkedList<Node> list, Node root) {

        if (null == root) return ;

        travel(list, root.left);
        list.add(new Node(root.val));
        travel(list, root.right);
    }
}

(3)剑指 Offer 54. 二叉搜索树的第k大节点

题目描述


给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4
示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 4

限制:

  • 1 ≤ k ≤ 二叉搜索树元素个数

题解


二叉搜索树,中序遍历后就是递增的。

思路:

  1. 先中序遍历
  2. 找第 k 个数即可。

AC 代码如下:

class Solution {
    public int kthLargest(TreeNode root, int k) {
        if (null == root) return -1;
        
        List<Integer> list = new LinkedList<>();
        
        travel(list, root);
        
        return list.get(list.size() - k);
    }

    private void travel(List<Integer> list, TreeNode root) {
        
        if (null == root) return;
        
        travel(list, root.left);
        list.add(root.val);
        travel(list, root.right);
    }
}

直接查找方式:

class Solution {
    int res, k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    void dfs(TreeNode root) {
        if(root == null) return;
        dfs(root.right);
        if(k == 0) return;
        if(--k == 0) res = root.val;
        dfs(root.left);
    }
}