今天做两道树的题目(虽然说很简单吧)。做的时候的唯一感觉是,我已经菜到连树的遍历都不会了吗……
第一道题,判断两个二叉树是否相同。这个很简单,按理来说两个二叉树一起遍历一遍就行了。第一反应还是递归吧,在树上的操作用迭代还是不太习惯。不过我不知道我怎么想的,居然拿了一个string来存储遍历的结果,然后进行字符串比较:
class Solution
{
private:
string ps;
string qs;
// 前序遍历并存储遍历过程
void traverseTree(TreeNode *root, string &store)
{
if (root)
{
store += to_string(root->val);
traverseTree(root->left, store);
traverseTree(root->right, store);
}
// 用" "代表null
else
{
store += " ";
}
}
public:
bool isSameTree(TreeNode *p, TreeNode *q)
{
traverseTree(p, this->ps);
traverseTree(q, this->qs);
return ps == qs;
}
}
回过头来看就完全没看懂,这个string是毫无意义的。事实上,更好的解法应该是这样:
bool isSameTree(TreeNode *p, TreeNode *q)
{
if (p == nullptr && q == nullptr)
{
return true;
}
if ((p == nullptr || q == nullptr) ||
p->val != q->val)
{
return false;
}
return isSameTree(p->left, q->left) &&
isSameTree(p->right, q->right);
}
至于用栈(或者像官方题解一样用队列)作为辅助空间来进行迭代,我实在是不习惯,就没有特别深究。
对称二叉树呢,其实就是在第一道题的基础上把顺序反了一下。我看评论区有很多人说想不到,我觉得很奇怪,这两道题连在一起,不就是在疯狂暗示么?
class Solution
{
private:
bool isSymmetric(TreeNode *p, TreeNode *q)
{
if (p == nullptr && q == nullptr)
{
return true;
}
if ((p == nullptr || q == nullptr) ||
p->val != q->val)
{
return false;
}
return isSymmetric(p->left, q->right) &&
isSymmetric(p->right, q->left);
}
public:
bool isSymmetric(TreeNode *root)
{
if (root == nullptr)
{
return true;
}
return isSymmetric(root->left, root->right);
}
};
后来想了一下,大概是官方题解里直接传入两个root,直接一步操作isSymmetric(root, root)
把人秀到了吧;其实没必要,而且这么搞似乎会增加不必要的开销。
我猜测一下,做和树有关的题目,是不是都有这么一个套路:
xxx foo(TreeNode *root)
{
// do sth
foo(root->left);
foo(root->right);
}
慢慢验证吧。