zoukankan      html  css  js  c++  java
  • 每日一练leetcode

    653. 两数之和 IV - 输入 BST

    给定一个二叉搜索树 root 和一个目标结果 k,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true

     

    • 二叉树的节点个数的范围是  [1, 104].
    • -104 <= Node.val <= 104
    • root 为二叉搜索树
    • -105 <= k <= 105

    方法一:使用HashSet

    如果存在两个元素之和为 kk,即 x+y=kx+y=k,并且已知 xx 是树上一个节点的值,则只需判断树上是否存在一个值为 yy 的节点,使得 y=k-xy=k−x。基于这种思想,在树的每个节点上遍历它的两棵子树(左子树和右子树),寻找另外一个匹配的数。在遍历过程中,将每个节点的值都放到一个 setset 中。

    对于每个值为 pp 的节点,在 setset 中检查是否存在 k-pk−p。如果存在,那么可以在该树上找到两个节点的和为 kk;否则,将 pp 放入到 setset 中。

    如果遍历完整棵树都没有找到一对节点和为 kk,那么该树上不存在两个和为 kk 的节点。

    作者:LeetCode
    链接:https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/solution/liang-shu-zhi-he-iv-by-leetcode/
    来源:力扣(LeetCode)

    /**
     * Definition for a binary tree node.
     * public 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;
     *     }
     * }
     */
    class Solution {
        public boolean findTarget(TreeNode root, int k) {
            Set<Integer> set = new HashSet();
            return find(root,k, set);
        }
        public boolean find(TreeNode root, int k, Set<Integer> set){
            if(root == null){
                return false;
            }
            if(set.contains(k-root.val)){
                return true;
            }
            set.add(root.val);
            return find(root.right, k, set)||find(root.left, k, set);
        }
    }
    

      

    执行用时: 3 ms
    内存消耗: 39.3 MB

     方法二:使用 BFS 和 HashSet

    本方法中,setset 的用途与 方法一 相同。但是本方法使用广度优先搜索遍历二叉树,这是一种非常常见的遍历方法。

    使用广度优先搜索查找一对节点和为 kk 的过程如下。首先维护一个与 方法一 用途相同的 setset。将根节点加入 queuequeue,然后执行以下步骤:

    从队列首部删除一个元素 pp。

    检查 setset 中是否存在 k-pk−p。如果存在,返回 True。

    否则,将 pp 加入 setset。然后将当前节点的左孩子和右孩子加入 queuequeue。

    重复步骤一至三,直到 queuequeue 为空。

    如果 queuequeue 为空,返回 False。

    按照以上步骤,逐层遍历二叉树。

    /**
     * Definition for a binary tree node.
     * public 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;
     *     }
     * }
     */
    class Solution {
        public boolean findTarget(TreeNode root, int k) {
            Set<Integer> set = new HashSet();
            Queue<TreeNode> queue = new LinkedList();
            queue.add(root);
            while(!queue.isEmpty()){
                if(queue.peek()!=null){
                    TreeNode node = queue.remove();
                    if(set.contains(k - node.val)){
                        return true;
                    }
                    set.add(node.val);
                    queue.add(node.left);
                    queue.add(node.right);
                }else{
                    queue.remove();
                }
    
            }
            return false;
        }
    
    }
    

      

    执行用时: 3 ms
    内存消耗: 39.9 MB

     方法三 使用 BST

    在本方法中利用 BST 的性质,BST 的中序遍历结果是按升序排列的。因此,中序遍历给定的 BST,并将遍历结果存储到 listlist 中。

    遍历完成后,使用两个指针 ll 和 rr 作为 listlist 的头部索引和尾部索引。然后执行以下操作:

    检查 ll 和 rr 索引处两元素之和是否等于 kk。如果是,立即返回 True。

    如果当前两元素之和小于 kk,则更新 ll 指向下一个元素。这是因为当我们需要增大两数之和时,应该增大较小数。

    如果当前两元素之和大于 kk,则更新 rr 指向上一个元素。这是因为当我们需要减小两数之和时,应该减小较大数。

    重复步骤一至三,直到左指针 ll 大于右指针 rr。

    如果左指针 ll 到右指针 rr 的右边,则返回 False。

    注意:在任何情况下,都不应该增大较大的数,也不应该减小较小的数。这是因为如果当前两数之和大于 kk,不应该首先增大 list[r]list[r] 的值。类似的,也不应该首先减小 list[l] 的值。

    /**
     * Definition for a binary tree node.
     * public 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;
     *     }
     * }
     */
    class Solution {
        public boolean findTarget(TreeNode root, int k) {
            List<Integer> list = new ArrayList();
            reTree(root, list);
            int l = 0;
            int r = list.size() - 1;
            while(l < r){
                int sum = list.get(l) + list.get(r);
                if (sum < k){
                    l++;
                }
                if(sum > k){
                    r--;
                }
                if(sum == k){
                    return true;
                }
                
            }
            return false;
       
        }
        public  void reTree(TreeNode root,List<Integer> list){
            if(root == null){
                return;
            }
            reTree(root.left,list);
            list.add(root.val);
            reTree(root.right,list);
    
        }
    
    }
    执行用时: 2 ms
    内存消耗: 39.9 MB
  • 相关阅读:
    文艺平衡树
    [BJOI2010] 严格次小生成树
    BZOJ3864 hero meet devil
    [NOI2010]能量采集(莫比乌斯反演)
    陌上花开(三维偏序)(cdq分治)
    树状数组套trie 模板
    SDOI2010粟粟的书架
    OI计算几何 简单学习笔记
    OI知识点|NOIP考点|省选考点|教程与学习笔记合集
    悬线法学习笔记
  • 原文地址:https://www.cnblogs.com/nenu/p/15033781.html
Copyright © 2011-2022 走看看