题目链接:
https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/
难度:中等
114. 二叉树展开为链表
给定一个二叉树,原地将它展开为一个单链表。
例如,给定二叉树
1
/ \
2 5
/ \ \
3 4 6
将其展开为:
1
\
2
\
3
\
4
\
5
\
6
这道题不算难 不过一开始没看懂要求是什么。。。
前序遍历放到一个数组里面 在遍历数组就可以了
前序遍历可以使用 递归或非递归(栈) 当然是选择非递归了 毕竟一般情况下递归的效率是比较低的。。。
/**
* 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:
void flatten(TreeNode* root) {
// 用来保存前序遍历过程中的node
auto vec=vector<TreeNode*>();
// 栈 回溯
auto sta=stack<TreeNode*>();
TreeNode *node=root;
while(!sta.empty()||node!=nullptr){
// 向左遍历
while(node!=nullptr){
vec.push_back(node);
sta.push(node);
node=node->left;
}
// 向左到头 回溯到上一个的node的右子树
node=sta.top();
sta.pop();
node=node->right;
}
// 最后一个node必为叶子节点所以本来就是nullptr
for(int i=1;i<vec.size();++i){
auto pre=vec.at(i-1);
auto cur=vec.at(i);
pre->left=nullptr;
pre->right=cur;
}
}
};
还可以继续优化 题解很强啊。。。
不需要vec记录访问顺序 直接转化为链表
class Solution {
public:
void flatten(TreeNode* root) {
if(root==nullptr){
return;
}
auto sta=stack<TreeNode*>();
sta.push(root);
// pre记录前一个
TreeNode *pre=nullptr;
while(!sta.empty()){
auto cur=sta.top();
sta.pop();
if(pre!=nullptr){
pre->left=nullptr;
pre->right=cur;
}
auto left=cur->left;
auto right=cur->right;
// right先进栈
if(right!=nullptr){
sta.push(right);
}
if(left!=nullptr){
sta.push(left);
}
pre=cur;
}
}
};
还有一种方法 嗯。。。 这种方法我是想不到的 官方牛皮 方向是寻找前驱结点
具体的操作: 对于所有结点枚举{
对于当前节点cur
若左子节点不为空:
则在其左子树中找到最右边的节点,作为前驱节点,将当前节点的右子节点赋给前驱节点的右子节点
然后将当前节点的左子节点赋给当前节点的右子节点,并将当前节点的左子节点设为空
若左子节点为空:cur=cur->right
}
我终究还是太菜了。。
class Solution {
public:
void flatten(TreeNode* root) {
TreeNode *cur=root;
while(cur!=nullptr){
if(cur->left!=nullptr){
auto node=cur->left;
auto t=node;
while(node->right!=nullptr){
node=node->right;
}
node->right=cur->right;
cur->right=t;
cur->left=nullptr;
}
cur=cur->right;
}
}
};