剑指Offer - 九度1503 - 二叉搜索树与双向链表
剑指Offer - 九度1503 - 二叉搜索树与双向链表
2014-02-05 23:39
- 题目描述:
-
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
- 输入:
-
输入可能包含多个测试样例。
对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。
接下来的n行,每行为一个二叉搜索树的先序遍历序列,其中左右子树若为空则用0代替。
- 输出:
-
对应每个测试案例,
输出将二叉搜索树转换成排序的双向链表后,从链表头至链表尾的遍历结果。
- 样例输入:
-
1
2 1 0 0 3 0 0
- 样例输出:
-
1 2 3
题意分析:
这道题要求将二叉搜索树转换成双向链表,我的思路是进行后序遍历。先将左右子树搞定以后,再处理根节点。
那么,怎么处理呢?在转换完成之后,根节点的左边是左子树最大的节点(左子树最偏右的),右边是右子树最小的节点(右子树最偏左的)。
因此,在递归过程中,需要获得这两个参数,具体做法请参见代码。其中最关键的四个参数:
1. pll:左子树最靠左的节点
2. plr:左子树最靠右的节点
3. prl:右子树最靠左的节点
4. prr:右子树最靠右的节点
虽然也可以通过O(h)的复杂度(h为树的高度)查找出上述四个节点,但那么做的话,就重复遍历了很多节点,整体复杂度也变成了O(n * log(n))。
所以我们在递归的过程中随时更新这些参数即可。
时间复杂度为O(n),空间复杂度O(n),n表示树的节点个数。
// 690545 zhuli19901106 1503 Accepted 点击此处查看所有case的执行结果 1024KB 2642B 70MS
// 201402041916
//#define MY_DEBUG
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; typedef struct st{
public:
int key;
struct st *ll;
struct st *rr;
st(int _key): key(_key) {}
}st; void convertBSTtoDoubleLinkedList(st *root, st *&left_most, st *&right_most)
{
if (root == NULL) {
return;
} if (root->ll == NULL && root->rr == NULL) {
left_most = root;
right_most = root;
} st *pll = NULL, *plr = NULL, *prl = NULL, *prr = NULL;
if (root->ll != NULL) {
convertBSTtoDoubleLinkedList(root->ll, pll, plr);
} else {
pll = plr = root;
}
if (root->rr != NULL) {
convertBSTtoDoubleLinkedList(root->rr, prl, prr);
} else {
prl = prr = root;
}
left_most = pll;
right_most = prr;
if (plr != root) {
plr->rr = root;
root->ll = plr;
}
if (prl != root) {
prl->ll = root;
root->rr = prl;
}
} void constructBST(st *&root)
{
int tmp; scanf("%d", &tmp);
if (tmp == ) {
root = NULL;
} else {
root = new st(tmp);
constructBST(root->ll);
constructBST(root->rr);
}
} #ifdef MY_DEBUG
void postorderTraversal(const st *root)
{
if (root == NULL) {
return;
}
postorderTraversal(root->ll);
postorderTraversal(root->rr);
printf("%d ", root->key);
}
#endif st *deleteList(st *head)
{
if (NULL == head) {
return head;
}
st *ptr1, *ptr2; ptr1 = head;
while (ptr1 != NULL) {
ptr2 = ptr1;
ptr1 = ptr1->rr;
delete ptr2;
} return NULL;
} st *deleteTree(st *root)
{
if (NULL == root) {
return NULL;
}
if (root->ll != NULL) {
root->ll = deleteTree(root->ll);
}
if (root->rr != NULL) {
root->rr = deleteTree(root->rr);
}
delete root;
return NULL;
} int main()
{
int cc, ci;
st *root = NULL;
st *left_most, *right_most, *ptr; while (scanf("%d", &cc) == ) {
for (ci = ; ci < cc; ++ci) {
root = NULL;
constructBST(root); // used to verify the tree
#ifdef MY_DEBUG
postorderTraversal(root);
printf("\n");
#endif left_most = right_most = NULL;
convertBSTtoDoubleLinkedList(root, left_most, right_most);
ptr = left_most;
while (ptr != NULL) {
printf("%d ", ptr->key);
ptr = ptr->rr;
}
printf("\n");
deleteList(left_most);
root = left_most = right_most = NULL;
}
} return ;
}
剑指Offer - 九度1503 - 二叉搜索树与双向链表的更多相关文章
- 剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列
剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列2013-11-23 03:16 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出 ...
- 剑指Offer:面试题27——二叉搜索树与双向链表(java实现)
问题描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路: 将树分为三部分:左子树,根结点,右子树. 1.我们要把根结点与左 ...
- 剑指offer(26)二叉搜索树与双向链表
题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 题目分析 要生成排序的双向列表,那么只能是中序遍历,因为中序遍历才能从小到 ...
- 【剑指Offer】26、二叉搜索树与双向链表
题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 解题思路: 首先要理解此题目的含义,在双向链表中,每个结 ...
- 剑指offer 面试题36.二叉搜索树与双向链表
中序递归,一个pre节点记录前一个节点 /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; Tre ...
- 剑指Offer - 九度1513 - 二进制中1的个数
剑指Offer - 九度1513 - 二进制中1的个数2013-11-29 23:35 题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 输入: 输入可能包含多个测试样例. ...
- 剑指Offer - 九度1384 - 二维数组中的查找
剑指Offer - 九度1384 - 二维数组中的查找2013-11-23 23:23 题目描述: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个 ...
- 剑指Offer:面试题24——二叉搜索树的后序遍历序列(java实现)
问题描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 思路: 1.首先后序遍历的结果是[(左子 ...
- 剑指offer(20)二叉搜索树与双向表
题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...
随机推荐
- 2018年第九届蓝桥杯【C++省赛B组】第二题 明码
汉字的字形存在于字库中,即便在今天,16点阵的字库也仍然使用广泛.16点阵的字库把每个汉字看成是16x16个像素信息.并把这些信息记录在字节中. 一个字节可以存储8位信息,用32个字节就可以存一个汉字 ...
- 2017.11.14 C语言---指针的学习
第八章 善于利用指针 (1)指针是什么 1.内存区每一个字节都有一个编号,这就是"地址".地址形象化的被称为"指针".它能通过以它为地址的内存单元.地址指向(* ...
- PMVS论文随笔(1)
博客园排版系统真的比较挫,可以访问我的github.io阅读 关于Unit的概念 在pmvs的源代码中,有一个函数是getUnit ,其函数如下(在PMVS2的windows版本代码,optim.cc ...
- getnumdevices.c && setgetdevicetype例程
getnumdevices.c代码 /* 文件名: getnumdevices.c * 功能 : 测试函数acc_get_num_devices(.) */ #include<stdio.h&g ...
- CNN训练中的技巧
转自: http://weibo.com/p/1001603816330729006673 说明:这个翻译应该是来自原文:http://yyue.blogspot.hk/2015/01/a-brief ...
- 子div作为遮罩层
效果图: 子div的代码:
- JS-输入数字输出大写中文
function(n) { var fraction = ['角', '分']; var digit = [ '零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', ...
- 【学时总结】◆学时·VI◆ SPLAY伸展树
◆学时·VI◆ SPLAY伸展树 平衡树之多,学之不尽也…… ◇算法概述 二叉排序树的一种,自动平衡,由 Tarjan 提出并实现.得名于特有的 Splay 操作. Splay操作:将节点u通过单旋. ...
- LeetCode-177:第N高的薪水
第N高的薪水与第二高的薪水,解题思路是一样的,只要对LeetCode-176的SQL做一下变形,便可以满足这题,详见:https://www.cnblogs.com/zouqf/p/10282392. ...
- dubbo 与Spring Cloud 对比
链接:https://www.zhihu.com/question/45413135/answer/242224410 近期也看到一些分享Spring Cloud的相关实施经验,这对于最近正在整理Sp ...