每日刷题记录 (八)

x33g5p2x  于2022-06-29 转载在 其他  
字(3.6k)|赞(0)|评价(0)|浏览(416)

第一题: 剑指 Offer II 052. 展平二叉搜索树

LeetCode: 剑指 Offer II 052. 展平二叉搜索树
描述:
给你一棵二叉搜索树,请 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。

解题思路:

  • 按照中序遍历的方式, 左 -> 根 -> 右
  • 让一个节点的右节点指向遍历到的节点
  • 循环的将遍历的节点都指向右节点处
  • 最后返回该节点的下一节点

代码实现:

class Solution {
	// 让pre.next表示头节点
    private TreeNode pre = new TreeNode();
    // 让tmp来指向添加节点的操作
    private TreeNode tmp = pre;
    public TreeNode increasingBST(TreeNode root) {
        if(root == null) return null;
        increasingBST(root.left);
        tmp.right = new TreeNode(root.val);
        tmp = tmp.right;
        increasingBST(root.right);
        return pre.right;
    }
}

第二题: 剑指 Offer II 053. 二叉搜索树中的中序后继

LeetCode: 剑指 Offer II 053. 二叉搜索树中的中序后继
描述:
给定一棵二叉搜索树和其中的一个节点 p ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null

节点 p 的后继是值比 p.val 大的节点中键值最小的节点,即按中序遍历的顺序节点 p 的下一个节点。

解题思路:

  • 循环直到 root为空.
  • 如果当前 root.val > p.val, 那么只可能在左树, 因为二叉搜索树右子树的节点的值都大于左子树节点的值. 记录下该节点. 然后让 root = root.left
  • 如果当前 root.val < p.val, 那么就从右树找. 让root = root.right

代码实现:

class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        TreeNode ans = null;
        while(root != null) {
        	// root.val > p.val 就不需要取右子树找了, 右边只会更大
            if(root.val > p.val){
            	// 每次都记录, 最终的ans就是最后需要的节点
                ans = root;
                root = root.left;
            }else{
                root = root.right;
            }
        }
        return ans;
    }
}

第三题: 剑指 Offer II 054. 所有大于等于节点的值之和

LeetCode: 剑指 Offer II 054. 所有大于等于节点的值之和

描述:
给定一个二叉搜索树,请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。

提醒一下,二叉搜索树满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

解题思路:

  • 这里按照中序遍历的思路, 不过这里使用 右 -> 根 -> 左 的方法
  • 每次将节点的值加起来. 然后替换节点的值 root.val += sum``sum=root.val

代码实现:

class Solution {
    private int sum = 0;
    public TreeNode convertBST(TreeNode root) {
        if(root == null) return null;
        convertBST(root.right);
        // 修改该节点的值
        root.val += sum;
        sum = root.val;
        convertBST(root.left);
        return root;
    }
}

第四题: 剑指 Offer II 055. 二叉搜索树迭代器

LeetCode: 剑指 Offer II 055. 二叉搜索树迭代器

描述:
实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:

  • BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
  • boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
  • int next()将指针向右移动,然后返回指针处的数字。
    注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。

可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

解题思路:

  1. 初始化的时候, 将节点以 中序遍历 的方法存入到list中
  2. next()的时候, 返回 index++ 节点的值 index初始为0
  3. hasNext()的时候, 只要 index!<list.size() 就是 true, 反之就是 false

代码实现:

class BSTIterator {
    private List<Integer> list = new ArrayList<>();
    private int index = 0;
    public BSTIterator(TreeNode root) {
        inorderBST(root);
    }
    public TreeNode inorderBST(TreeNode root) {
        if(root == null) return null;
        inorderBST(root.left);
        list.add(root.val);
        inorderBST(root.right);
        return root;
    }
    
    public int next() {
        return list.get(index++);
    }
    
    public boolean hasNext() {
        if(index < list.size()) {
            return true;
        }else{
            return false;
        }
    }
}

第五题: 剑指 Offer II 056. 二叉搜索树中两个节点之和

LeetCode: 剑指 Offer II 056. 二叉搜索树中两个节点之和

描述:
给定一个二叉搜索树的 根节点 root 和一个整数 k , 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k 。假设二叉搜索树中节点的值均唯一。

解题思路:

  • 这里使用的是 哈希表 思路

  • 对于当前节点的值 root.val 我们判断 k - root.val 是否存在哈希表中.

  • 如果存在, 那么就有两个节点加起来的值为 k

  • 如果不存在, 那么就将该节点的值加入 哈希表中

代码实现:

class Solution {
    private Set<Integer> set = new HashSet<>();
    public boolean findTarget(TreeNode root, int k) {
        if(root == null) return false;
        // 如果 k-root.val 的值 存在, 就返回true;
        if(set.contains(k-root.val)) return true;
        // 如果 不存在, 就添加到 哈希表上.
        set.add(root.val);
        return findTarget(root.left,k) || findTarget(root.right,k);
    }
}

第六题: 剑指 Offer II 059. 数据流的第 K 大数值

LeetCode: 剑指 Offer II 059. 数据流的第 K 大数值

描述:
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

请实现 KthLargest 类:

  • KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
  • int add(int val)val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

解题思路:

  • 这里使用 优先级队列, 来进行添加.

  • 初始化的时候, 初始一个优先级队列 大小为 k 的 小根堆, 然后将 nums 数组添加到这个优先级队列中.

  • add操作的时候,

  • 如果当前队列没满, 就直接入队, 如果满了,

  • 判断当前队顶元素, 是否小于这个插入的值, 如果小于, 弹出栈顶元素, 然后入队这个值

代码实现:

class KthLargest {
    private int k;
    private PriorityQueue<Integer> pq;
    public KthLargest(int k, int[] nums) {
        this.k = k;
        pq = new PriorityQueue<>(k,(o1,o2)->(o1-o2));
        for(int num : nums) {
            add(num);
        }
    }
    
    public int add(int val) {
        if(pq.size() < k) {
            pq.offer(val);
        }else{
            if(val > pq.peek()) {
                pq.poll();
                pq.offer(val);
            }
        }
        return pq.peek();
    }
}

相关文章