LeetCode 653. Two Sum IV - Input is a BST

题目

Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.

Example 1:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7

Target = 9

Output: True

Example 2:

Input: 
    5
   / \
  3   6
 / \   \
2   4   7

Target = 28

Output: False

这道题就是把2sum中的数组换成了BST的形式,刚开始也是脑子不灵光没想到怎么做,其实最直觉的方法就是因为BST的inorder traversal是升序排列的,所以可以进行一次遍历把这棵树转换成一个数组,然后对这个数组进行普通的(2023.1.2 edit:应该是sorted的)2sum就可以了。时间复杂度是遍历树的复杂度O(n),空间也是O(n)因为要把它们都存到一个数组里。

Runtime: 2 ms, faster than 93.75% of Java online submissions for Two Sum IV - Input is a BST.

Memory Usage: 41.7 MB, less than 71.43% of Java online submissions for Two Sum IV - Input is a BST.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean findTarget(TreeNode root, int k) {
        List<Integer> nums = new ArrayList<>();
        inorder(root, nums);
        int pStart = 0;
        int pEnd = nums.size() - 1;
            
        while (pStart < pEnd) {
            int sum = nums.get(pStart) + nums.get(pEnd);
            if (sum > k) {
                pEnd--;
            } else if (sum < k) {
                pStart++;
            } else {
                return true;
            }
        }
        
        return false;
    }
    
    private void inorder(TreeNode root, List<Integer> nums) {
        if (root == null) {
            return;
        }
        
        inorder(root.left, nums);
        nums.add(root.val);
        inorder(root.right, nums);
    }
}

 2022.12.24

想到了能转成array,却忘了array是sorted,可以直接2 pointers做。写2 pointers的时候在动high和low的时候也忘了,需要根据sum和k的大小来选择移动谁,需要复习复习。

/**
 * 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 {
    List<Integer> list = new ArrayList<>();

    public boolean findTarget(TreeNode root, int k) {
        inorder(root);
        int low = 0;
        int high = list.size() - 1;
        while (low < high) {
            int sum = list.get(low) + list.get(high);
            if (sum == k) {
                return true;
            } else if (sum < k) {
                low++;
            } else {
                high--;
            }
        }
        return false;
    }

    private void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        inorder(root.left);
        list.add(root.val);
        inorder(root.right);
    }
}

 

上面这种方法虽然是用上了BST的性质,但实际上对这个数组access了两次,其实是可以优化的,比如一遍遍历一边把它塞进hashset里(写到这里突然意识到之前忘了哪道题用hashmap其实并不需要存key-value pair,只需要快速查找,所以直接用hashset即可)。这样的话其实就用不上BST的性质了,普通任意一棵树都可以,所以这里也有两种做法,一种是DFS,一种是BFS。

DFS的做法就是在普通的DFS函数中,如果root == null返回false说明以这个root为根的子树找不到配对的,然后继续查set中是否有可以和它配对的,有的话就直接返回true了,然后把当前的数字加入set,接下来再对root的左右子树进行DFS递归调用这个函数,如果它的左右子树中任意有一个能配对就返回true,否则返回false。(最后return的这个地方刚开始没想清楚,后面要多复习这种return方法)时间复杂度O(n),空间复杂度O(n)。

Runtime: 2 ms, faster than 93.75% of Java online submissions for Two Sum IV - Input is a BST.

Memory Usage: 41.7 MB, less than 71.43% of Java online submissions for Two Sum IV - Input is a BST.

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

2022.12.24

DFS其实也挺简单,刚开始想成了inorder traversal,其实好像这么写确实是类似于inorder,先判断root,再判断左,最后判断右,但其实又跟traversal order没啥太大关系,就是一普通的递归DFS罢了。代码就看上面的吧,都一样。


BFS在这道题里并没有比DFS复杂,按照BFS的常规套路建一个queue来放root,然后while queue不为空的时候每次取出队头的node,判断这个node在set中有没有可以配对的,有的话直接true,没有的话把它放进set并且把它的左右子节点放进queue。这里被坑了一下,就是每次取队头元素的时候要判断它是不是null,因为有可能有只有一个叶子节点的情况。

Runtime: 3 ms, faster than 40.78% of Java online submissions for Two Sum IV - Input is a BST.

Memory Usage: 41.6 MB, less than 73.21% of Java online submissions for Two Sum IV - Input is a BST.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Set<Integer> nums = new HashSet<>();
        if (root == null) {
            return false;
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        
        while (!queue.isEmpty()) {
            TreeNode node = queue.remove();
            if (node != null) {  // attention to null in the tree
                if (nums.contains(k - node.val)) {
                    return true;
                }
                nums.add(node.val);
                queue.add(node.left);
                queue.add(node.right);
            }
        }
        
        return false;
    }
}

2022.12.24

这是看到这道题以后第一个想到的方法。时隔这么久再回头做树,印象最深刻的还是经典的用queue进行BFS啊。也是顺利地就写出了代码,很感动,但是代码没有之前写的那么简洁,把left和right分开写了。

/**
 * 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);
        set.add(root.val);
        while (queue.size() != 0) {
            TreeNode top = queue.remove();
            if (top.left != null) {
                if (set.contains(k - top.left.val)) {
                    return true;
                }
                queue.add(top.left);
                set.add(top.left.val);
            }
            if (top.right != null) {
                if (set.contains(k - top.right.val)) {
                    return true;
                }
                queue.add(top.right);
                set.add(top.right.val);
            }
        }
        return false;    
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值