标签:复杂 render family default 一个栈 复杂度 sea splay cli
看见一句话,感觉很好,记录一下:贵有恒,何须三更醒五更眠。最无益,莫过一日曝十日寒。
谈到中序遍历,常规的思路一个是递归,一个是迭代,其中迭代的思想需要显式的维护一个栈,以此来辅助遍历,但这连两种方法都不能达到O1的空间复杂度。刷题的时候看到一个巧妙的方法,利用二叉树中的闲散指针,每个节点访问两次,以时间换取空间的方法,O(2n)的时间也不会多出太久,达到了O1的空间占用。这种方法叫做Morris中序遍历。
原题为力扣中99. 恢复二叉搜索树,是一道难度不高的题,但贵在一题多解,这个方法很值得学习。
算法步骤如下:
其实整个过程我们就多做一步:将当前节点左子树中最右边的节点指向它,这样在左子树遍历完成后我们通过这个指向走回了 xx,且能再通过这个知晓我们已经遍历完成了左子树,而不用再通过栈来维护,省去了栈的空间复杂度。
代码实现如下:
void recoverTree(TreeNode* root) { TreeNode* x=nullptr; TreeNode* y=nullptr; TreeNode* pre=nullptr; TreeNode* predecessor=nullptr; while(root){ if(root->left){ //有左子树,遍历找到前序节点,然后指向root节点。 predecessor=root->left; while(predecessor->right && predecessor->right!=root){ predecessor=predecessor->right; } if(predecessor->right){ //有后续,需断开 if(pre&& pre->val>root->val){ y=root; if(x==nullptr){ x=pre; } } predecessor->right=nullptr; pre=root; root=root->right; } else{ //不需要断开 predecessor->right=root; root=root->left; } } else{ //无左子树 if(pre&& pre->val>root->val){ y=root; if(x==nullptr){ x=pre; } } pre=root; root=root->right; } } swap(x->val,y->val); }
标签:复杂 render family default 一个栈 复杂度 sea splay cli
原文地址:https://www.cnblogs.com/awangkuo/p/14964604.html