一开始着这代码框里都是啥呀,一点看不懂,和pat风格完全不同,后来仔细分析,发现这就是《算法笔记》里面提到的结构体的构造函数,瞬间如释重负~~
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
构造器1:无参构造器
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
构造器2:只赋值data的构造器
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
构造器3:三个全部赋值的构造器
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> vi;
vector<int> preorderTraversal(TreeNode* root) {
if(root == NULL)
return vi;
vi.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
return vi;
}
};
思路:
既然题目给出的函数是返回一个 vector,那么我就先定义一个vector,然后就是简单的递归先序遍历,递归边界是null,如果没到递归边界,就:
先序遍历:根、左、右
根:压入元素
左:递归左子树
右:递归右子树。
先序非递归写法
class Solution {
public:
vector<int> vi;
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st; // 这里的stack应该定义为TreeNode*型,而不是int型,因为压入栈的是一个结点
TreeNode* p = root; // 定义一个指针指向根结点
while(p || !st.empty()){ // 判断如果p非空,且 栈非空
if(p != NULL){ // 如果p非空,访问根结点,
vi.push_back(p->val);
st.push(p); // 压入栈,方便返回的时候再去访问右子树
p = p->left; // 访问左子树
}else{
TreeNode* q = st.top(); // 取栈顶元素,为访问右子树做准备
st.pop(); // 弹出栈
p = q->right; // 访问右子树
}
}
return vi;
}
};
此算法参考自,B站上青岛大学-王卓老师的视频~
中序递归写法
class Solution {
public:
vector<int> vi;
vector<int> inorderTraversal(TreeNode* root) {
if(root == NULL)
return vi;
// 中序遍历:左、根、右
inorderTraversal(root->left);
vi.push_back(root->val);
inorderTraversal(root->right);
return vi;
}
};
中序非递归
class Solution {
public:
vector<int> vi;
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* p = root;
// 左、根、右
while(p || !st.empty()){
if(p){
st.push(p);
p = p->left; // 左
}else{
TreeNode* q = st.top();
vi.push_back(q->val); // 根
st.pop();
p = q->right; // 右
}
}
return vi;
}
};
后序递归
class Solution {
public:
vector<int> vi;
vector<int> postorderTraversal(TreeNode* root) {
if(root == NULL)
return vi;
// 左、右、根
postorderTraversal(root->left);
postorderTraversal(root->right);
vi.push_back(root->val);
return vi;
}
};
层序遍历
不太熟悉
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if (root == NULL)
return {};
vector<vector<int>> vi; //二维
queue<TreeNode*> q; // 定义一个队列,
q.push(root); // 根结点入队
while (!q.empty()) {
vector<int> oneLevel; // 该层也定义一个队列
// 去掉根节点,此时 queue 里的元素就是下一层的所有节点,用一个 for 循环遍历它们
for (int i = q.size(); i > 0; --i) {
TreeNode* now = q.front(); // 新建一个结点指向队列的头元素,方便出队之后 入队它的左右孩子
q.pop(); // 出队
oneLevel.push_back(now->val); // 把当前这个出队的元素 压入到该层的vector中
if (now->left != NULL)
q.push(now->left);
if (now->right != NULL)
q.push(now->right);
}
vi.push_back(oneLevel); // 把该层的vector压入到 总的vector中
}
return vi;
}
};