Given a tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only 1 right child.html
Example 1: Input: [5,3,6,2,4,null,8,1,null,null,null,7,9] 5 / \ 3 6 / \ \ 2 4 8 / / \ 1 7 9 Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9] 1 \ 2 \ 3 \ 4 \ 5 \ 6 \ 7 \ 8 \ 9
Note:node
这道题给了一棵二叉树,让咱们对其进行重排序,使得最左结点变为根结点,并且整个树不能有左子结点,如题目中的例子所示,排序后的结果是一条向右下方延伸的直线。若是咱们仔细观察题目中的例子,能够发现遍历顺序实际上是 左->根->右,就是中序遍历的顺序,虽然题目中没说是二叉搜索树,但这并不影响咱们进行中序遍历。咱们先从最简单的例子开始分析,当 root 为空时,直接返回空,当 root 没有左右子结点时,也是直接返回 root。当 root 只有一个左子结点时,咱们此时要把其左子结点变为根结点,将原来的根结点变成其原来的左子结点的右子结点。可是若是 root 只有一个右子结点,仍是保持原来的顺序不变,而若 root 同时具备左右子结点的话,仍是要将左子结点变为根结点,而后把以前的根结点连到右子结点上,以前的右子结点还连在以前的根结点上,这个不用改变。咱们能够发现,最麻烦的就是左子结点了,须要和其根结点交换位置,因此对于每一个结点,咱们须要知道其父结点的位置,那么就在递归函数的参数中传入一个 pre 结点,再对左右子结点调用递归函数时,都将其下一个要链接的结点传入,这个 pre 结点多是当前结点或者当前结点的父结点。git
在递归函数中,首先判空,若当前结点为空的话,直接返回 pre 结点,由于到空结点的时候,说明已经遍历到叶结点的下方了,那么 pre 就是这个叶结点了。因为是中序遍历,因此要先对左子结点调用递归函数,将返回值保存到一个新的结点 res 中,表示的意义是此时 node 的左子树已经所有捋直了,并且根结点就是 res,并且 node 结点自己也被连到了捋直后的左子树下,即此时左子结点和根结点已经完成了交换位子,固然要断开原来的链接,因此将 node->left 赋值为 nullptr。而后再对 node 的右子结点调用递归函数,注意此时的 pre 不能传入 node 自己,而是要传 node 结点的 pre 结点,这是由于右子结点后面要链接的是 node 的父结点,好比兑入下面这例子:github
4 / 2 / \ 1 3
当运行到结点3的时候,pre 应该带入的是结点4,这样就能够把结点4连到结点3的右下方,从而正确的捋直,参见代码以下:函数
解法一:code
class Solution { public: TreeNode* increasingBST(TreeNode* root) { return helper(root, nullptr); } TreeNode* helper(TreeNode* node, TreeNode* pre) { if (!node) return pre; TreeNode* res = helper(node->left, node); node->left = nullptr; node->right = helper(node->right, pre); return res; } };
咱们也能够采用中序遍历的迭代形式,使用栈来辅助。因为根结点可能会产生变化,因此咱们须要一个 dummy 结点,还须要一个 pre 结点。在 while 循环中,先找到最左结点,把路径上的全部结点都压入栈,而后取出栈顶元素,将其连到 pre 的右子结点上,并将 pre 更新为其右子结点,而后断开栈顶元素的左子结点链接,并将其移动到右子结点上,并继续循环,最终返回 dummy 的右子结点便可,参见代码以下:htm
解法二:blog
class Solution { public: TreeNode* increasingBST(TreeNode* root) { TreeNode *dummy = new TreeNode(-1), *pre = dummy; stack<TreeNode*> st; while (root || !st.empty()) { while (root) { st.push(root); root = root->left; } root = st.top(); st.pop(); pre->right = root; pre = pre->right; root->left = nullptr; root = root->right; } return dummy->right; } };
Github 同步地址:排序
https://github.com/grandyang/leetcode/issues/897递归
参考资料:
https://leetcode.com/problems/increasing-order-search-tree/
https://leetcode.com/problems/increasing-order-search-tree/discuss/251290/C%2B%2B-short-iterative