给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
class Solution {//方法一:二分 断开链表 得考虑delete 麻烦
public:
TreeNode* sortedListToBST(ListNode* head) {
if(!head)return nullptr;
if(!head->next)return new TreeNode(head->val);
ListNode *mid=head,*end=head,*temp=nullptr;
while(end&&end->next){
temp=mid;
mid=mid->next;
end=end->next->next;
}
TreeNode *res=new TreeNode(mid->val);
if(temp){
temp->next=nullptr;
res->left=sortedListToBST(head);
}
else
res->left=nullptr;
temp=mid->next;
delete mid;
res->right=sortedListToBST(temp);
return res;
}
};
class Solution {方法二:不断开链表
public:
TreeNode* sortedListToBST(ListNode* head) {
if(!head)return nullptr;
return BuildTree(head,nullptr);
}
TreeNode* BuildTree(ListNode* head,ListNode* tail){
if(head==tail)return nullptr;
if(head->next==tail)return new TreeNode(head->val);
ListNode *mid=head,*end=head;
do{
mid=mid->next;
end=end->next->next;
}while(end!=tail&&end->next!=tail);
TreeNode *res=new TreeNode(mid->val);
res->left=BuildTree(head,mid);
res->right=BuildTree(mid->next,tail);
return res;
}
};
②快慢指针:
1)mid偏右:
a.slow=head;fast=head; do{}while(fast&&fast->next);
b.slow=head;fast=head->next; while(fast&&fast->next){};
2)mid偏左:
a.slow=head;fast=head; while(fast&&fast->next){};
b.slow=head;fast=head->next; do{}while(fast&&fast->next);
class Solution {//方法二变形:链表存数组
vector<int>nums;
public:
TreeNode* sortedListToBST(ListNode* head) {
if(!head)return nullptr;
while(head)
nums.push_back(head->val),head=head->next;
return BuildTree(0,nums.size()-1);
}
TreeNode* BuildTree(int start,int end){
if(start>end)return nullptr;
if(start==end)return new TreeNode(nums[start]);
int mid=start+((end-start)>>1);
TreeNode *res=new TreeNode(nums[mid]);
res->left=BuildTree(start,mid-1);
res->right=BuildTree(mid+1,end);
return res;
}
};
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
示例:
输入:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}
输出:{"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1}
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。
class Solution {
public:
Node* connect(Node* root) {
if(!root)return root;
helper(root,root->left);
//root->next=nullptr;
helper(root,root->right);
return root;
}
void helper(Node* parent,Node* cur){//递归 中序遍历
if(!cur)return;
helper(cur,cur->left);
if(parent->left==cur)cur->next=parent->right;
else if(parent->next)cur->next=parent->next->left;
helper(cur,cur->right);
}
};
class Solution {
public:
Node* connect(Node* root) {
if(!root)return root;
Node *LevelOrderLeft=root;
while(LevelOrderLeft->left){//层序遍历:next代替队列实现常数级额外空间
Node *LevelOrderHead=LevelOrderLeft;
while(LevelOrderHead){
LevelOrderHead->left->next=LevelOrderHead->right;
if(LevelOrderHead->next)
LevelOrderHead->right->next=LevelOrderHead->next->left;
LevelOrderHead=LevelOrderHead->next;
}
LevelOrderLeft=LevelOrderLeft->left;
}
return root;
}
};
给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
进阶:
你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
示例:
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。
提示:
树中的节点数小于 6000
-100 <= node.val <= 100
class Solution {
public:
Node* connect(Node* root) {
if(!root)return root;
Node *LevelOrderLeft=root;//层序遍历每一层的第一个元素:无子/有一子/有二子
while(LevelOrderLeft){
Node *LevelOrderHead=LevelOrderLeft;
while(LevelOrderHead&&!LevelOrderHead->left&&!LevelOrderHead->right)LevelOrderHead=LevelOrderHead->next;//寻找每一层的第一个有效元素:至少有一子
if(!LevelOrderHead)break;
Node *nextLevel=nullptr,*pre=nullptr;
//nextLevel层序遍历下一层的第一个元素
//pre表示每一层的有效元素的前一个有效元素的最后一子,初始化为第一个有效元素的最后一子
if(LevelOrderHead->left&&LevelOrderHead->right){//有效元素有二子
nextLevel=LevelOrderHead->left;
LevelOrderHead->left->next=LevelOrderHead->right;
pre=LevelOrderHead->right;
}
else if(LevelOrderHead->left){//有效元素只有左子
nextLevel=LevelOrderHead->left;
pre=LevelOrderHead->left;
}
else{//有效元素只有右子
nextLevel=LevelOrderHead->right;
pre=LevelOrderHead->right;
}
for(LevelOrderHead=LevelOrderHead->next;LevelOrderHead;LevelOrderHead=LevelOrderHead->next){//遍历每一层元素
if(!LevelOrderHead->left&&!LevelOrderHead->right)continue;//过滤得到有效元素
//对有效元素进行next拼接:有二子/有左子/有右子
if(LevelOrderHead->left&&LevelOrderHead->right){
pre->next=LevelOrderHead->left;
LevelOrderHead->left->next=LevelOrderHead->right;
pre=LevelOrderHead->right;
}
else if(LevelOrderHead->left){
pre->next=LevelOrderHead->left;
pre=LevelOrderHead->left;
}
else{
pre->next=LevelOrderHead->right;
pre=LevelOrderHead->right;
}
}
LevelOrderLeft=nextLevel;
}
return root;
}
};
/*思路
在当前层时,把下一层第一个节点用nextLevel记录下来,然后遍历当前层的时候,把下面一层串起来,当前层遍历完,通过nextLevel可以开始下一层的遍历(同样重复上述, 将nextLevel记录下下层第一个节点,然后遍历该层, 并把下面一层串起来)
*/
class Solution {
public:
Node* connect(Node* root) {
if(!root)return root;
Node *curLevel=root,*nextLevel=new Node(0);//下一层的伪头节点
while(curLevel){
Node *nextLevelEnd=nextLevel;
while(curLevel){
if(curLevel->left){
nextLevelEnd->next=curLevel->left;
nextLevelEnd=nextLevelEnd->next;
}
if(curLevel->right){
nextLevelEnd->next=curLevel->right;
nextLevelEnd=nextLevelEnd->next;
}
curLevel=curLevel->next;
}
if(nextLevel==nextLevelEnd)break;
curLevel=nextLevel->next;
}
return root;
}
};