二叉搜索树的中位数
Given a BST (Binary search Tree) how will you find median in that?
Constraints:
* No extra memory.
* Function should be reentrant (No static, global variables allowed.)
* Median for even no of nodes will be the average of 2 middle elements and for odd no of terms will be middle element only.
* Algorithm should be efficient in terms of complexity.
中文不需要赘述了,就是二叉搜索树如何高效地找到中位数,不希望申请内存,不要static/global的变量来实现。
第一反应就是中序遍历就是排序了,但是如果要计数的话,我们需要一个额外的变量,这样恐怕需要或是静态或者全局变量了,故不可以用。但是我们其他很多次都碰到了那样类似的问题,如何把一个二叉树原地转化成双向链表,那时候还有点觉得题目没意思,没啥用处。但是在这里,作用得以体现。假如有形如
10
/ /
6 14
/ / / /
4 8 12 16
的二叉树转化成了4=6=8=10=12=14=16这样一个双链表,那后面的问题就变成了如何在4=6=8=10=12=14=16里面找到中间节点了,这对于我们习惯了2个快慢指针追赶的小朋友来说不算问题了。
下面就是写的一个实现:
[cpp] view plaincopy
#include <iostream>
typedef struct bstNode
{
int data;
bstNode* pLeft;
bstNode* pRight;
bstNode()
{
data = 0;
pLeft = NULL;
pRight = NULL;
}
}bstNode;
void bst2dll (bstNode* pNode, bstNode*& pTail )
{
// in-order traverse
if (pNode == NULL) return ;
if (pNode->pLeft) bst2dll(pNode->pLeft,pTail);
bstNode* pCurrent = pNode;
pCurrent->pLeft = pTail;
if (pTail)
pTail->pRight = pCurrent;
pTail = pCurrent;
if(pNode->pRight) bst2dll(pNode->pRight, pTail);
}
// parameter is the original root
// return the new double linked list head
int medianInBST ( bstNode* pRoot )
{
bstNode* pTail = NULL;
bst2dll(pRoot,pTail);
// dummy handling here
if (pTail == NULL) return -1;
bstNode* pFast = pTail;
bstNode* pSlow = pTail;
while (pFast&&pSlow)
{
if (pFast->pLeft==NULL)
return pSlow->data;
else if (pFast->pLeft != NULL && pFast->pLeft->pLeft == NULL)
return (pSlow->data + pSlow->pLeft->data)>>1;
else
{
pFast = pFast->pLeft;
pFast = pFast->pLeft;
pSlow = pSlow->pLeft;
}
}
}
// test case
/*
10
/ /
6 14
/ / / /
4 8 12 16
*/
bstNode* buildupTree()
{
// level 1
bstNode* pRoot = new bstNode;
pRoot->data = 10;
//level2
bstNode* pNewL = new bstNode;
pNewL->data = 6;
bstNode* pNewR = new bstNode;
pNewR->data = 14;
//level3
bstNode* pNewLL = new bstNode;
pNewLL->data = 4;
bstNode* pNewLR = new bstNode;
pNewLR->data = 8;
bstNode* pNewRL = new bstNode;
pNewRL->data = 12;
bstNode* pNewRR = new bstNode;
pNewRR->data = 16;
pRoot->pLeft = pNewL;
pRoot->pRight = pNewR;
pNewL->pLeft = pNewLL;
pNewL->pRight = pNewLR;
pNewR->pLeft = pNewRL;
pNewR->pRight = pNewRR;
return pRoot;
}
void main()
{
bstNode* pRoot = buildupTree();
std::cout<<medianInBST(pRoot)<<std::endl;
system("pause");
}
说实话这样的题目还是比较喜欢的,考到了很多的概念和想法,
a.中序遍历
b.BST转化成DLL
c.寻找链表的中间节点
如果任何一个问题割裂开了问, 都是比较容易解决的。困难就在于如何用已知的办法组合地解决未知的问题,发人深思,余是以记之。
转载:http://blog.csdn.net/hhygcy/article/details/4654305