题目确实很简单,构建一棵中序遍历顺序的树。
中序遍历
理解中序遍历,因为中序遍历顺序的每一次结果已经就是答案顺序,所以只需要在有一个空间存储当前的结果的尾节点,一一追加到结果中即可。
对于中序遍历到的第一个节点,需要将当前节点直接存储为结果尾节点,最好再有一个空间存储当前节点,以便于记录最终结果的头节点。
最终代码为:
struct TreeNode *cur, *ans; void dfs(struct TreeNode *root) { if (!root) return; dfs(root->left); if (!cur) { ans = cur = root; } else { cur->left = NULL, cur->right = root; cur = cur->right; } dfs(root->right); } struct TreeNode *increasingBST(struct TreeNode *root) { ans = cur = NULL; dfs(root); return ans; }
当然也可以参考官方题解方法二,提前申请一个空间,最终结果成为带头节点,而且这个方法不用考虑尾节点为空指针的情况。
反中序遍历
我们可以逆序思考,将中序遍历改为逆中序,这样就变成不断往结果链表的前面追加节点,同样可以规避空指针的判断,还可以减少一个额外的空间记录结果的头节点,因为递归结束后,当前节点即为头节点。
struct TreeNode *cur; void dfs(struct TreeNode *root) { if (!root) return; dfs(root->right); root->right = cur, cur = root; dfs(root->left); root->left = NULL; } struct TreeNode *increasingBST(struct TreeNode *root) { cur = NULL; dfs(root); return cur; }
拓展
不太喜欢全局变量,所以最终代码其实长这样,同样基于反中序遍历。
struct TreeNode *dfs(struct TreeNode *root, struct TreeNode *right) { struct TreeNode *ans = right; if (!root) return ans; root->right = dfs(root->right, ans); ans = dfs(root->left, root); root->left = NULL; return ans; } struct TreeNode *increasingBST(struct TreeNode *root) { return dfs(root, NULL); }