题目来源
题目描述
将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。
对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
特别地,我们希望可以 就地 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。
示例 1 :
- 输入: root = [4, 2, 5, 1, 3];
- 输出: [1, 2, 3, 4, 5] ;
解释: 下图显示的是转化之后的二叉搜索树,图中的实线表示节点间的后继关系,而虚线表示节点间的前序关系。
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:
TreeNode* treeToDoublyList(TreeNode *head) {
}
};
题目解析
递归套路
如果root == null,直接返回null
否则:
对于X的每一棵子树,X需要子树的:
- 转完之后链表的头节点
- 转弯之后链表的尾节点
#include <assert.h>
#include <iostream>
#include <algorithm>
#include <functional>
#include <utility>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <iterator>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
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 {
struct Info{
TreeNode * start;
TreeNode *end;
Info(TreeNode * start, TreeNode * end) : start(start), end(end){
}
};
Info *process(TreeNode *x){
if(x == nullptr){
return new Info(nullptr, nullptr);
}
auto left = process(x->left);
auto right = process(x->right);
if(left->end != nullptr){
left->end->right = x;
}
x->left = left->end;
x->right = right->start;
if(right->start != nullptr){
right->start->left = x;
}
return new Info(left->start != nullptr ? left->start : x ,
right->end != nullptr ? right->end : x);
}
public:
TreeNode* treeToDoublyList(TreeNode *head) {
if(head == nullptr){
return nullptr;
}
auto all = process(head);
all->start->left = all->end;
all->end->right = all->start;
return all->start;
}
};