淼淼刷力扣

引言:全部算法建立在无重复点的基础上

本人初次尝试写博客,希望各位看官大佬多多包容
有错误希望巨巨们提出来,我一定会及时改正,谢谢大家
在自己最好的年纪,找到了未来的目标
还有1年奋斗刷题,明年去面试实习,加油!
<该题的另一种递归解法见我另一篇博客>
递归重整二叉树

题外话:

这个类型的题目十分重要,非常多的大厂愿意考,所以说这道题是重中之重,非常锻炼思维,所以有共同目标的友友们一定要练好此题,加油,冲冲冲!
在这里插入图片描述

老样子,先看看题目要求:

在这里插入图片描述

简单分划重组二叉树

矛盾点

正常向左添加节点都没问题,但是我不到什么时候加到右节点,又该把该节点加到谁的右边!这就是设计迭代算法最大的矛盾之处!

前序知识:

1、先序遍历可以把每个节点理解成一个个根节点,但是具体连到左还是右不能明确(个人理解)。中根遍历就是疯狂向左走,所以可以理解成从当前节点疯狂左走可以到的最左的节点(个人理解)。这二者可以用开始的时候理解,先序第一个节点必定是根,他疯狂左走到的边界一定是中根第一个节点,那么这段范围就是全都连在左边的范围(后面有图印证)
2、(最重要的来了)对于前序遍历中的任意两个连续节点 u 和 v,根据前序遍历的流程,我们可以知道 u 和 v 只有两种可能的关系:
1)v 是 u 的左儿子。这是因为在遍历到 u 之后,下一个遍历的节点就是 u 的左儿子,即 v;
2)u 没有左儿子,并且 v 是 u 的某个祖先节点(或者 u 本身)的右儿子。如果 u 没有左儿子,那么下一个遍历的节点就是 u 的右儿子。如果 u 没有右儿子,我们就会向上回溯,直到遇到第一个有右儿子的节点。

整体迭代思路:

1、根据矛盾点以及前序知识,那我们就针对性的设置一个专用栈空间(因为中序和先序本质上得到的是相反的),存储可能连有右儿子的所有节点,初始时将根节点压入。我们需要知道我每次从当前节点疯狂向左走最多到谁那里,根据中序的特点,可以根据初始的时候理解,所以初始值赋值为0。
2、这些节点都有可能连右节点,所以入专门的栈,一旦发现当前栈顶是最左边界了,就说明现在这个节点就该连在某个节点右面。
3、因为中根遍历走到最左后回溯,如果你发现每次回溯的值(即将专用指针右移得到的值)和栈顶一样,说明二者单线连,因为栈里面的元素就是这样单线向左连下来的
4、一旦找到了不同说明出现了不同,回溯的时候走岔了路,就把最后弹出来的节点右面连上该节点,把该节点入栈,以为她也有权利拥有右节点
5、重复上述2-4过程。

具体分析

力扣官方题解
这道题官方题解写的很好,有完整的模拟流程,这里我引用一下,嘻嘻嘻。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

注:这是大体思路,具体写的时候找个简单的例子,一边模拟一边写,很简单就有了,再多找复杂例子验证即可。

class Solution {
public:
	TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
		if (preorder.size() == 0) {//特殊情况判断
			return nullptr;
		}
		TreeNode* root = new TreeNode(preorder.front());//初始化
		stack<TreeNode*> can_link_right;//专有栈
		can_link_right.push(root);
		int index = 0;//初始化
		for (int i = 1; i < preorder.size(); i++) {
			TreeNode* item = new TreeNode(preorder[i]);
			if (can_link_right.top()->val != inorder[index]) {//没有走到当前节点下左边界
				can_link_right.top()->left = item;
				can_link_right.push(item);
			}
			else {//走到左边界,那就要找当前节点是栈里面谁的右节点
				TreeNode* temp = nullptr;
				while (can_link_right.size() != 0 && can_link_right.top()->val == inorder[index]) {
					temp = can_link_right.top();
					can_link_right.pop();
					index++;
				}
				temp->right = item;
				can_link_right.push(item);
			}
		}
		return root;
	}
};


(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

时间复杂度:O(n),其中 n是树中的节点个数。

Sum Up

1、先找常规思路解法,发现不行(处理不了右节点),找到矛盾点,针对矛盾点进行编程优化处理,就可得到最优解,博主就是这个解题历程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JLU_LYM

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值