LeetCode打卡day21——两数之和 IV - 输入 BST

174 阅读1分钟

“Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。”

一、题目描述:

653. 两数之和 IV - 输入 BST

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

 

示例 1:

image.png

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


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

二、思路分析:

  1. 双指针+中序遍历 对于二叉搜索树中序遍历得到的数组是升序,这样我们只需要用双指针指向一头一尾,判断是否符合target,大于则尾指针--,小于则头指针++,直到两者重合或者等于目标
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {boolean}
 */
var findTarget = function(root, k) {
    const inorder=function(root){
        if(root===null)return
        inorder(root.left)
        nodes.push(root.val)
        inorder(root.right)
    }
    let nodes=[]
    inorder(root)
    let l=0,r=nodes.length-1
    while(l<r){
        let sum=nodes[l]+nodes[r]
        if(sum===k)return true
        else if(sum<k){
            l++;
        }else {
            r--;
        }
    }
    return false
};
  1. 优化:迭代+双指针+中序遍历 对于方法一,我们是先完整遍历整个二叉树,这样一定会消耗O(n)的空间,我们可以一次遍历。首先先一直遍历最左边的节点left并记录到到栈leftStack,同样一直遍历最右边节点right并记录到rightStack。这样就得到第一个方法的首位节点,这栈顶就是上一个节点,同时我们需要加入上一个节点的右/左节点,这样才能升序。
var findTarget = function(root, k) {
    const getLeft = (stack) => {
        const root = stack.pop();
        let node = root.right;
        while (node) {
            stack.push(node);
            node = node.left;
        }
        return root;
    }

    const getRight = (stack) => {
        const root = stack.pop();
        let node = root.left;
        while (node) {
            stack.push(node);
            node = node.right;
        }
        return root;
    };

    let left = root, right = root;
    const leftStack = [];
    const rightStack = [];
    leftStack.push(left);
    while (left.left) {
        leftStack.push(left.left);
        left = left.left;
    }
    rightStack.push(right);
    while (right.right) {
        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;
}
  1. 深度遍历+哈希表 因为是两个节点值相加判断等于target,故我们可以先把其中一边的节点加入Set集合,这样遍历到另一个节点判断是否有target-x的值是能找到。
var findTarget = function(root, k) {
    const getLeft = (stack) => {
        const root = stack.pop();
        let node = root.right;
        while (node) {
            stack.push(node);
            node = node.left;
        }
        return root;
    }

    const getRight = (stack) => {
        const root = stack.pop();
        let node = root.left;
        while (node) {
            stack.push(node);
            node = node.right;
        }
        return root;
    };

    let left = root, right = root;
    const leftStack = [];
    const rightStack = [];
    leftStack.push(left);
    while (left.left) {
        leftStack.push(left.left);
        left = left.left;
    }
    rightStack.push(right);
    while (right.right) {
        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;
}

4、广度遍历+哈希表 能深度遍历肯定能广度遍历

class Solution:
    def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
        s = set()
        q = deque([root])
        while q:
            node = q.popleft()
            if k - node.val in s:
                return True
            s.add(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        return False