二分木のシーケンストラバーサル
アイデア:レイヤーシーケンストラバーサルにキューを使用します。各操作は、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:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
queue<TreeNode*> que;
if(root) que.push(root);
while(!que.empty()){
int siz=que.size();
vector<int> a;
while(siz--){
TreeNode* now=que.front();
que.pop();
a.push_back(now->val);
if(now->left) que.push(now->left);
if(now->right) que.push(now->right);
}
ans.push_back(a);
}
return ans;
}
};
二分木のプレオーダートラバーサル
再帰
アイデア:プレオーダーは左右なので、最初に値をスタブし、次にdfsの左右のサブツリーをスタブします
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
ans.push_back(root->val);
dfs(root->left);
dfs(root->right);
}
vector<int> preorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非再帰的
アイデア:再帰は実際にはスタックであることがわかっているので、再帰的でない場合は、スタックを使用してシミュレートします。
次に、事前注文が左右に行われ、スタックの最上位が後で追加されるためです。
したがって、左ノードと右ノードをスタックにスローするときは、最初に右ノードをドロップし、次に左ノードをドロップして、スタックの一番上が左ノードになるようにする必要があります。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
if(root) sta.push(root);
while(!sta.empty()){
TreeNode* now=sta.top();
sta.pop();
ans.push_back(now->val);
if(now->right) sta.push(now->right);
if(now->left) sta.push(now->left);
}
return ans;
}
};
二分木のポストオーダートラバーサル
再帰
アイデア:後順は左右なので、最初に左右のサブツリーをdfsし、次に値をスタブ化します
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
dfs(root->left);
dfs(root->right);
ans.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非再帰的
アイデア:私たちは、行きがけが左右、および後順が左右されることを知っている私たちは前順、その後、逆(先行順)に保存されているノードの順序を逆にした場合は、左右の中心地です。以前の非によると、 -プレオーダートラバーサルの再帰バージョン。次に、左の息子を最初にスタックに配置し、次に右の息子をスタックに配置するように変更します。これは右中央と左中央で、ベクトル全体が左右に反転します。これが後順です。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
if(root) sta.push(root);
while(!sta.empty()){
TreeNode* now=sta.top();
sta.pop();
ans.push_back(now->val);
//与前序非递归相比,这两行顺序换了换而已
if(now->left) sta.push(now->left);
if(now->right) sta.push(now->right);
}
reverse(ans.begin(),ans.end());//中右左 反转 左右中
return ans;
}
};
二分木の順序通りの走査
再帰
アイデア:中央の順序は左、中央、右なので、最初に左側のサブツリーをdfsし、次に値をスタブし、最後に右側のサブツリーをdfsします。
/**
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
void dfs(TreeNode* root){
if(!root) return ;
dfs(root->left);
ans.push_back(root->val);
dfs(root->right);
}
vector<int> inorderTraversal(TreeNode* root) {
dfs(root);
return ans;
}
};
非再帰的
アイデア:以前の非再帰バージョンでは、実際には最初にノードの値をスタブ化するため、残念ながら、これは以前の非再帰アプローチとあまり一致していません。次に、中間の順序が左、中央、右であることがわかります。実際、左のサブツリーは常に再帰的です。
したがって、基本的な考え方は、南の壁にぶつかったり、振り返ったりしないことです。つまり、左側のサブツリーが空でない場合は、繰り返し続けます。
空ですか?すでに左側のサブツリーをトラバースした最後のノードを取得するので、右側のサブツリーのトラバースを開始します。そして、それは左、中央、右なので、右のサブツリーの左のサブツリーをトラバースし続けます。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> ans;
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
while(root || !sta.empty()){
if(root){
//没撞南墙 一直遍历左子树
sta.push(root); //保存过来的结点
root=root->left;
}
else{
//撞墙了
root=sta.top();//取出上一个遍历的点
sta.pop();
ans.push_back(root->val);//
root=root->right;//开始跑右子树
}
}
return ans;
}
};