题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
一、解题
二叉搜索树,顾名思义,就是根节点左子树都比根节点元素小,右子树的节点都比根节点大的树,搜索的速度取决于树的高度,如果树的构造接近完全二叉树,那么搜索效率为lgn,如果高度接近n,那么搜索效率就为n,n为节点数。
解题思路,二叉搜索树的中序遍历结果就是一个顺序数组,所以只有中序遍历就可以了。
#pragma once
#include <vector>
namespace search_tree
{
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(nullptr), right(nullptr) {
}
};
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree == nullptr)
{
return nullptr;
}
std::vector<TreeNode *> vec;
foreach(pRootOfTree, vec);
auto pNode = vec[0];
pNode->left = nullptr;
for (int i = 1; i < vec.size(); i++)
{
pNode->right = vec[i];
vec[i]->left = pNode;
vec[i]->right = nullptr;
pNode = vec[i];
}
return vec[0];
}
void foreach(TreeNode* pRootOfTree, std::vector<TreeNode *> &vec)
{
if (pRootOfTree == nullptr)
{
return;
}
foreach(pRootOfTree->left, vec);
vec.push_back(pRootOfTree);
foreach(pRootOfTree->right, vec);
}
};
}
二、优化
我们引入了一个vector数组来纪录,遍历的节点指针,其实可以不需要,只要一个pro指针就够了,用pro来纪录上一个遍历的节点就可以了
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree == nullptr)
{
return nullptr;
}
TreeNode *pro = nullptr;
foreach(pRootOfTree, pro);
return _first;
}
void foreach(TreeNode* pRootOfTree, std::vector<TreeNode *> &vec)
{
if (pRootOfTree == nullptr)
{
return;
}
foreach(pRootOfTree->left, vec);
vec.push_back(pRootOfTree);
foreach(pRootOfTree->right, vec);
}
void foreach(TreeNode* pRootOfTree, TreeNode *&pro)
{
if (pRootOfTree == nullptr)
{
return;
}
foreach(pRootOfTree->left, pro);
pRootOfTree->left = pro;
if (pro)
pro->right = pRootOfTree;
if (first)
{
_first = pRootOfTree;
first = false;
}
pro = pRootOfTree;
foreach(pRootOfTree->right, pro);
}
TreeNode *_first = nullptr;
bool first = true;
三、再优化
我们知道,递归占用的空间其实比vector占用的空间大的多,所有实际上,vector消去只在时间上有优势,在空间上的优化微乎其微,所以非递归的实现才是最优化的。
实现暂无