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
  • 相关阅读:
    BZOJ 4260: Codechef REBXOR(01trie+思维)
    17个CSS知识点整理
    30个很棒的jQuery幻灯片放映插件
    gitHub客户端Desktop的安装使用总结 ---基础篇
    jQuery 瀑布流动态加载效果
    【转】自适应网页设计(Responsive Web Design)
    响应式布局这件小事
    查找指定节点之后的下一个元素节点getNextElement(node)
    转 JavaScript 运动框架 Step by step
    JS常用函数封装
  • 原文地址:https://www.cnblogs.com/nenu/p/15033781.html
Copyright © 2011-2022 走看看