LeetCode——653. 两数之和 IV - 输入 BST(Java)

题目描述

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

示例 1:
输入: root = [5,3,6,2,4,null,7], k = 9
输出: true

示例 2:
输入: root = [5,3,6,2,4,null,7], k = 28
输出: false

题解思路

这次的判断两数之和和二叉搜索树结合,我们可以借助二叉搜索树的性质来解决两数之和的问题

如果我们采用传统方式,我们可以直接深度或者广度优先遍历结合递归、队列和哈希表判断

如果借助二叉搜索树中序遍历元素会顺序排序的规律,也可以采用双指针的方式判断

也可以将双指针直接放置在二叉搜索树上进行移动搜索,不过需要找好左右指针的下一个节点的位置

正确代码

class FindTargetSolution {
    Set<Integer> set = new HashSet<>();
    List<Integer> list = new ArrayList<>();

    // 深度优先遍历 + 哈希表
    public boolean findTarget01(TreeNode root, int k) {
        if (root == null) {
            return false;
        }
        if (set.contains(k - root.val)) {
            return true;
        }

        set.add(root.val);
        return findTarget01(root.left, k) || findTarget01(root.right, k);
    }

    // 广度优先遍历 + 哈希表
    public boolean findTarget02(TreeNode root, int k) {
        ArrayDeque<Object> queue = new ArrayDeque<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = (TreeNode) queue.poll();

            if (set.contains(k - node.val)) {
                return true;
            }
            set.add(node.val);
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
        return false;
    }

    // 深度优先遍历 + 中序遍历 + 双指针
    public boolean findTarget03(TreeNode root, int k) {
        inorderTraversal(root);
        int left = 0, right = list.size() - 1;
        while (left < right) {
            if (list.get(left) + list.get(right) == k) {
                return true;
            } if (list.get(left) + list.get(right) < k) {
                left++;
            } else {
                right--;
            }
        }
        return false;
    }

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

    // 迭代 + 中序遍历 + 双指针
    public boolean findTarget04(TreeNode root, int k) {
        TreeNode left = root, right = root;
        ArrayDeque<TreeNode> leftStack = new ArrayDeque<>();
        ArrayDeque<TreeNode> rightStack = new ArrayDeque<>();

        leftStack.push(left);
        while (left.left != null) {
            leftStack.push(left.left);
            left = left.left;
        }
        rightStack.push(right);
        while (right.right != null) {
            rightStack.push(right.right);
            right = right.right;
        }
        while (left != right) {
            if (left.val + right.val == k) {
                return true;
            }
            if (left.val + right.val < k) {
                left = getLeft(leftStack);
            } else {
                right = getRight(rightStack);
            }
        }
        return false;
    }

    private TreeNode getLeft(Deque<TreeNode> stack) {
        TreeNode root = stack.pop();
        TreeNode node = root.right;

        while (node != null) {
            stack.push(node);
            node = node.left;
        }
        return root;
    }

    private TreeNode getRight(Deque<TreeNode> stack) {
        TreeNode root = stack.pop();
        TreeNode node = root.left;

        while (node != null) {
            stack.push(node);
            node = node.right;
        }
        return root;
    }
}

总结

两数之和问题作为leetCode的第一个问题,当时只会暴力求解的我根本不知道用哈希表存储差值来简化计算

到现在第四道两数之和已经掺杂了各种数据结构,也知晓了各种解题思路,也算是对自己的一种鼓励吧

但是算法的路要有很长的路要走,学到现在也只是冰山一角而已,路漫漫其修远兮,吾将上下而求索。
posted @ 2022-03-21 14:13  21岁还不是架构师  阅读(35)  评论(0编辑  收藏  举报