OJ-leetcode-117. 填充每个节点的下一个右侧节点指针II(中等二叉树)

这篇博客介绍了如何填充二叉树每个节点的next指针,使其指向右侧节点。作者提供了两种思路,分别是层次遍历和递归遍历,其中递归方法的空间复杂度为O(1)。示例代码展示了如何实现这两个方法,并给出了结果。最后,还展示了一个简洁的递归解法作为优秀题解。
摘要由CSDN通过智能技术生成

目录

题目

思路1

代码

结果

思路2

代码

结果

优秀题解

提升笔记


 

题目

给定一个二叉树

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


链接:https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii

通过读题可以明确,大致有三种思路,空间复杂度为O(n)级、递归解题、空间复杂度O(1)级。O(n)级应该是层次遍历,官方应该是希望我们使用递归并且空间复杂度O(1)。

1 2 4 -1 -1 5 -1 -1 3 -1 7 -1 -1

思路1

代码

	// 思路1 层次遍历
	Node* connect(Node* root) {
		if (!root)return nullptr;
		queue<Node*> q;
		Node* front;
		q.emplace(root);
		while (!q.empty())
		{
			int n = q.size();
			//cout << "本层元素个数:"<<n<<endl;
			Node* left = nullptr;//同一层左侧节点
			//连接同层的next
			for (int i = 0; i < n; ++i)
			{	
				front = q.front();
				q.pop();
				if (front->left) q.emplace(front->left);
				if (front->right)q.emplace(front->right);
				if (0 != i)
				{
					left->next = front;
					//cout << left->val << "与" << front->val << "已连接" << endl;
				}
				left = front;	
			}
		}
		return root;
	}

结果

结果

思路2

利用next遍历本层,不使用队列,遍历本层时将下一层使用next连接,并记录下一层头结点head

本层遍历结束后,转到下一层的head节点继续遍历,直到head为空

一层遍历时流程图如下:

一层的遍历流程图

代码

class Solution {
public:
	Node* connect(Node* root) {
		if (!root)return nullptr;
		Node* level = root;  //当前层节点
		Node* head = nullptr;//下一层的头结点,用于转到下一层
		Node* lastNext = nullptr;// 上一个next
		// 使用next遍历当前层,将下一层使用next连起来
		while (level)
		{
			//cout << "本层:" <<level->val<< endl;
			// 若有左孩子,连接一下
			if (level->left)
			{
				// 本层头结点已定
				if (head)
				{ 
					lastNext->next = level->left;
					//cout << lastNext->val << "连接" << level->left->val << endl;
					lastNext = lastNext->next;
				}
				// 本层头结点未定 level为本层第一个节点且有左孩子
				else { 
					head = level->left;
					//cout << "下一层头结点" << head->val << endl;
					lastNext = level->left; 
				}
			}
			//若有右孩子,连接一下
			if(level->right)
			{
				// 本层头结点已定
				if (head)
				{
					lastNext->next = level->right; 
					//cout << lastNext->val << "连接" << level->right->val << endl;
					lastNext = lastNext->next;
				}
				// 本层头结点未定 level为本层第一个节点且有右孩子
				else {
					head = level->right;
					//cout << "下一层头结点" << head->val << endl;
					lastNext = level->right;
				}
			}
			// 本层没结束
			if(level->next)level = level->next;
			// 本层已结束 转至本层头结点的孩子 若左右孩子均为空,level为空,结束
			else
			{
                                if(!head)break;
				level = head;
				//cout << "转至" <<level->val<<"层"<< endl;
				// 重置下一层的头结点
				head = nullptr;
			}
		}
		return root;
	}
};

结果

结果截图

优秀题解

简洁递归

class Solution {
public:
    Node* connect(Node* root) {
        if(root and (root->left or root->right)){
            if(root->left and root->right) root->left->next = root->right;
            
            Node *node = root->right ? root->right : root->left;
            Node *head = root->next;
            while (head and not (head->left or head->right)){
                head = head->next;
            }
            node->next = head ? (head->left ? head->left : head->right) : nullptr;
            
            connect(root->right);
            connect(root->left);
        }
        return root;
    }
};

提升笔记

1. 利用已有的next

 

更多内容:OJ网站题目分类,分难度整理笔记(leetcode、牛客网)

喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lady_killer9

感谢您的打赏,我会加倍努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值