25 二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:分为循环版本和递归版本。
循环版本:
二叉搜索树的中序遍历就是递增序列,所以本题本质就是中序遍历。有两点非常需要注意:
1)开始自己认为需要对链表的首尾节点进行特殊处理,比如开始节点需要left指向nullptr,但是画个图就会非常明显,中序遍历是左中右的顺序,所以头节点是遍历到最左边的叶子节点才开始处理,此时头结点left和right指针都指向nullptr,同理尾节点也是一样的,所以不需要进行特殊处理,需要注意的时候因为最后需要返回一个头节点,所以需要一个bool变量记录第一次遍历得到的头结点保存起来,后面进行return。
2)开始自己想的是将中序遍历的结果使用一个数组保存下来,但是不需要这么做,只需要遍历的过程中,进行交换即可,一个传入的root变量,一个pre节点,
root -> left = pre;
pre -> right = root;
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: TreeNode* Convert(TreeNode* pRootOfTree){ if(pRootOfTree == nullptr){ return nullptr; } //inorder stack<TreeNode*> s; TreeNode* pre = nullptr; TreeNode* root = pre; bool isFirst = true; while(!s.empty() || pRootOfTree != nullptr){ while(pRootOfTree != nullptr){ s.push(pRootOfTree); pRootOfTree = pRootOfTree -> left; } if(!s.empty()){ pRootOfTree = s.top(); s.pop(); if(isFirst){ isFirst = false; pre = pRootOfTree; root = pre; } else{//举例子,最左边的最右边的节点都是叶子节点,左右都是指向null,所以不需要特殊处理 pre -> right = pRootOfTree; pRootOfTree -> left = pre; pre = pRootOfTree; } pRootOfTree = pRootOfTree -> right; } } return root; } };
2、递归版本
将左子树转换为有序双向链表,然后找到左子树对应链表的最后一个节点leftLast,将leftLast和root节点连接起来,然后对右子树进行同样的处理,得到右子树对应的链表头结点是rightHead,将root和rightHead连接起来,放回结果的时候需要判断leftHead是否为空,为空的时候需要返回root。
这里关键的理解就是helper这个递归函数每次返回的是一个链表的头结点,不管是左子树还是右子树调用返回的都是对应部分的头结点。
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: TreeNode* helper(TreeNode* root){ if(root == nullptr){ return nullptr; } TreeNode* leftHead = helper(root -> left); TreeNode* leftLast = leftHead; if(leftLast != nullptr){ while(leftLast != nullptr && leftLast -> right != nullptr){//find last left node leftLast = leftLast -> right; } leftLast -> right = root; root -> left = leftLast; } TreeNode* rightHead = helper(root -> right); if(rightHead != nullptr){ root -> right = rightHead; rightHead -> left = root; } return (leftHead != nullptr) ? leftHead : root; } TreeNode* Convert(TreeNode* pRootOfTree){ if(pRootOfTree == nullptr){ return nullptr; } return helper(pRootOfTree); } };