引言
这个和之前两数之和问题相差不大,区别在于数据结构的不同,之前第一题那个存储数据用的是数组,这里用的是BST树
原题
给定一个二叉搜索树 root 和一个目标结果 k,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。
两数之和 IV - 输入 BST
BST 树
BST 树的主要特点就是节点的大小大于它左孩子的大小,小于它右孩子的大小
做法
我的做法参考题解
哈希 + dfs
先用哈希表把数字存起来,然后再遍历 BST树 。思路比较简单,就是直接哈希+遍历。感觉没有用到BST树得特性
class Solution {
private:
unordered_set<int>map;
public:
bool findTarget(TreeNode* root, int k) {
if(root==nullptr)return false;
if(map.count(k-root->val)){
return true;
}
map.insert(root->val);
return findTarget(root->left,k)||findTarget(root->right,k);
}
};
哈希+bfs
这个和上面的dfs方法类似,自不必多说。但是bfs运行起来时间和空间都比dfs要少
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
unordered_set<int>map;
queue<TreeNode*>que;
que.push(root);
while(!que.empty()){
TreeNode* current = que.front();
que.pop();
if(map.count(k-current->val)){
return true;
}
map.insert(current->val);
if(current->left!=nullptr){
que.push(current->left);
}
if(current->right != nullptr){
que.push(current->right);
}
}
return false;
}
};
dfs排序,双向列表
因为bfs的特性, 可以用中序遍历将它转换为一个有序数组。 然后就直接用两个指针left、right双向遍历
class Solution {
private:
vector<int>list;
public:
void inorderTraversal(TreeNode* root){
if(root == nullptr) return;
inorderTraversal(root->left);
list.push_back(root->val);
inorderTraversal(root->right);
}
bool findTarget(TreeNode* root, int k) {
inorderTraversal(root);
int left= 0;
int right = list.size() - 1;
int sum = 0;
while(left<right){
sum = list[left] + list[right];
if(sum == k) return true;
if(sum<k) left++;
else right--;
}
return false;
}
};
迭代 + 双向列表
这个方法思想也和上面那个差不多,只不过将递归转为了迭代。并且用到了stack这个数据结构。有一说一,要理解起来还真不容易。
讲一下步骤:
- 从root开始,将它所有的左节点压入leftStack栈中,将它的所有右节点压入rightStack中,这时候栈的头部都是值最小或者最大的指针
- 然后开始遍历
- 如果结果刚好满足,则return true; 如果小于,则调用getLeft函数,弹出并且返回栈中的下一个元素,往往比前面的元素要大,同时将该指针的right指针的所有左节点都压入栈中
class Solution {
private:
stack<TreeNode*> leftStack;
stack<TreeNode*> rightStack;
TreeNode* getLeft(){
TreeNode* root = leftStack.top();
leftStack.pop();
TreeNode* node = root ->right;
while(node!=nullptr){
leftStack.push(node);
node = node->left;
}
return root;
}
TreeNode* getRight(){
TreeNode* root = rightStack.top();
rightStack.pop();
TreeNode* node = root ->left;
while(node!=nullptr){
rightStack.push(node);
node = node->right;
}
return root;
}
public:
bool findTarget(TreeNode* root, int k) {
TreeNode* leftNode = root;
TreeNode* rightNode = root;
while(leftNode->left!=nullptr){
leftStack.push(leftNode);
leftNode = leftNode -> left;
}
leftStack.push(leftNode);
while(rightNode->right!=nullptr){
rightStack.push(rightNode);
rightNode = rightNode->right;
}
rightStack.push(rightNode);
while(leftNode != rightNode){
cout<<leftNode->val<<" "<<rightNode->val<<endl;
if(leftNode->val + rightNode->val == k) return true;
if(leftNode->val + rightNode->val < k ){
//if(!leftStack.size())return false;
leftNode = getLeft();
}
else {
//if(!rightStack.size())return false;
rightNode = getRight();
}
}
return false;
}
};