给定一个二叉搜索树 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

    可以先遍历完毕后根据遍历结果再查找,那么从遍历结果中判断两数之和就类似于 001. 两数之和

    1. public boolean findTarget(TreeNode root, int k) {
    2. List<Integer> valList = new ArrayList<>();
    3. order(root,valList);
    4. return towSum(valList, k);
    5. }
    6. public boolean towSum(List<Integer> valList, int target) {
    7. for(int i = 0; i < valList.size(); i++) {
    8. for(int j = 0; j < valList.size(); j++) {
    9. if (i != j && valList.get(i) + valList.get(j) == target) {
    10. return true;
    11. }
    12. }
    13. }
    14. return false;
    15. }
    16. private void order(TreeNode node, List<Integer> valList) {
    17. if (node == null) {
    18. return;
    19. }
    20. valList.add(node.val);
    21. order(node.left, valList);
    22. order(node.right, valList);
    23. }

    算法的优化变成了对 towSum 的优化:

    1. public boolean findTarget(TreeNode root, int k) {
    2. List<Integer> valList = new ArrayList<>();
    3. order(root,valList);
    4. return towSum(valList, k);
    5. }
    6. public boolean towSum(List<Integer> valList, int target) {
    7. Map<Integer, Integer> map = new HashMap<>();
    8. for(int i = 0; i < valList.size(); i++) {
    9. map.put(valList.get(i), i);
    10. }
    11. for(int i = 0; i < valList.size(); i++) {
    12. int diff = target - valList.get(i);
    13. if (map.containsKey(diff) && map.get(diff) != i) {
    14. return true;
    15. }
    16. }
    17. return false;
    18. }
    19. private void order(TreeNode node, List<Integer> valList) {
    20. if (node == null) {
    21. return;
    22. }
    23. valList.add(node.val);
    24. order(node.left, valList);
    25. order(node.right, valList);
    26. }

    可以继续优化,减少一次对结果的遍历

    1. public boolean findTarget(TreeNode root, int k) {
    2. List<Integer> valList = new ArrayList<>();
    3. order(root,valList);
    4. return towSum(valList, k);
    5. }
    6. public boolean towSum(List<Integer> valList, int target) {
    7. Map<Integer, Integer> map = new HashMap<>();
    8. for(int i = 0; i < valList.size(); i++) {
    9. int diff = target - valList.get(i);
    10. if (map.containsKey(diff) && map.get(diff) != i) {
    11. return true;
    12. }
    13. map.put(valList.get(i), i);
    14. }
    15. return false;
    16. }
    17. private void order(TreeNode node, List<Integer> valList) {
    18. if (node == null) {
    19. return;
    20. }
    21. valList.add(node.val);
    22. order(node.left, valList);
    23. order(node.right, valList);
    24. }

    同理可以继续优化,边遍历边比较,无需先遍历一次获取结果

    1. HashMap<Integer, Integer> valMap = new HashMap<>();
    2. boolean isHasTarget = false;
    3. public boolean findTarget(TreeNode root, int k) {
    4. order(root, k);
    5. return isHasTarget;
    6. }
    7. private void order(TreeNode node, int k) {
    8. if (node == null) {
    9. return;
    10. }
    11. // 比较当前值加上已经遍历过的节点中的某一个相加是否等于目标值
    12. if (valMap.containsKey(k - node.val)) {
    13. isHasTarget = true;
    14. }
    15. // 若没有则继续放入遍历结果集中
    16. valMap.put(node.val, node.val);
    17. order(node.left, k);
    18. order(node.right, k);
    19. }

    并且考虑到如果树是二叉搜索树,那么中序遍历可以获取一个升序的有序数组,而对有序数组获取两数之和类似于 167. 两数之和 II - 输入有序数组,有序数组可以利用双指针

    1. public boolean findTarget(TreeNode root, int k) {
    2. List<Integer> valList = new ArrayList<>();
    3. order(root,valList);
    4. return towSum(valList, k);
    5. }
    6. public boolean towSum(List<Integer> valList, int target) {
    7. int left = 0, right = valList.size() - 1;
    8. while (left < right) {
    9. if (valList.get(left) + valList.get(right) == target) {
    10. return true;
    11. }
    12. if (valList.get(left) + valList.get(right) < target) {
    13. left++;
    14. } else {
    15. right--;
    16. }
    17. }
    18. return false;
    19. }
    20. private void order(TreeNode node, List<Integer> valList) {
    21. if (node == null) {
    22. return;
    23. }
    24. order(node.left, valList);
    25. valList.add(node.val);
    26. order(node.right, valList);
    27. }