剑指 Offer 26. 树的子结构
一、自己的思路
既然是子树,那么肯定是A包含B进去的。
那么就可以遍历A 的时候,找到了和B根节点一样的节点。
就开始遍历B节点,同时将A节点做同样的遍历:
- 如果A节点没跟上,就说明:当前A节点向下不包含B树。
- 如果B树都遍历完了,说明A树包含了B树。
上面当前A节点向下不包含B树时,需要退出,继续遍历A树,循环往复下去。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(B==nullptr||A==nullptr)return false;
TreeNode* temp =A;
stack<TreeNode* > mystk;
while(temp!=nullptr||!mystk.empty())
{
while(temp != nullptr)
{
mystk.push(temp);
temp = temp->left;
}
temp = mystk.top();
mystk.pop();
if(temp->val == B->val)
{
stack<TreeNode* > mystkB,mystkA;
TreeNode* cur_A = temp,*cur_B = B;
bool break_ = false;
while(cur_B!=nullptr||!mystkB.empty())
{
while(cur_B != nullptr)
{
if(cur_A == nullptr)
{
break_ = true;
break;
}
mystkB.push(cur_B);
cur_B = cur_B->left;
mystkA.push(cur_A);
cur_A = cur_A->left;
}
if(break_) break;
cur_B = mystkB.top();
mystkB.pop();
cur_A = mystkA.top();
mystkA.pop();
if(cur_B->val != cur_A->val) break;
cur_B = cur_B->right;
cur_A = cur_A->right;
}
if(cur_B == nullptr) return true;
}
temp = temp->right;
}
return false;
}
};
这样复杂度为O(nm) n、m为两棵树的节点个数。
实现效果不是很理想
二、剑指offer 的做法:
1.递归遍历
和我的思路基本一致,但是代码量少了很多。
时间复杂度一样的,但是提交执行速度快了一点。
我觉得这个递归的消耗更多了,但是反而比我迭代的快。
自己分析的原因是因为,我不停的创建栈、指针,又不停的销毁。
而递归实现的,都在进程栈中,不用创建销毁,只需要入栈出栈,这点快一点。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool DFS(TreeNode* A, TreeNode* B) {
if(B == nullptr) return true;
if(A ==nullptr ||A->val != B->val) return false;
return DFS(A->left,B->left) && DFS(A->right,B->right);
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
return (A!=nullptr && B!= nullptr) &&(DFS(A,B)||isSubStructure(A->left,B)||isSubStructure(A->right,B));
}
};
考察的点:
- 二叉树有大量指针操作,每次使用指针之前都得考虑一下,有没有可能操作的是nullptr,应该怎么处理。
- 递归编程的思想。
- 代码鲁棒性的考虑,指针操作需要有相应的防御性编程的思想。
总结
刷题还是刷的太少了,很多方面考虑的不周全。
畏惧递归思想,递归并不是不高效,要看使用的方式。
拿到题,先思考考察的点是什么。