算法面试题之求前1000大&在树上判断节点父子关系
2015-01-13 14:19
357 查看
一、有10亿个杂乱无章的数,怎样最快地求出其中前1000大的数。
想答对这个题是非常简单的,建立一个大小为1000的小根堆就可以了。这个堆满足两个性质:
1.堆中的元素个数总是小于等于1000的
2.堆顶取出的元素总是这个堆里面最小的那一个
这样,这个题可以这样做:
二、一棵树节点1,
2, 3, ... , n. 怎样实现:先进行O(n)预处理,然后任给两个节点,用O(1)判断它们的父子关系
这个题目是DFS序的简单应用,首先来看看什么是DFS序,对于一棵树,有下面4条边:
1-2,1-3,2-4,2-5
那么,它的DFS序是:1,2,4,5,3,这里只是通过一次简单的深度优先搜索把每个节点访问的次序标了出来,如果每个节点在被访问的这一刻记录一次,访问结束的时候再记录一次,那又能是什么样子呢?代码是这样的:
此时,上面这幅图,它的dfs序变成了:1,2,4,4,5,5,2,3,3,1。
观察这个序列,可以发现:节点i是节点j的祖先,当且仅当节点i出现的两个位置x1,x2在节点j出现的两个位置y1,y2的两边,也就是x1<y1<y2<x2。所以,在生成dfs序的时候顺便记录每个节点dfs序出现的位置,之后每读入一个询问,直接O(1)判断并输出就可以了。
三. 给定一个二叉树,求其中N(N>=2)个节点的最近公共祖先节点。
这道题跟上面那道题解法非常像,首先求出来dfs序,拿第二题为例,dfs序为1,2,4,4,5,5,2,3,3,1,此时,要求4,5,3三个节点的最近公共祖先,怎么求呢?直接从4,5,3dfs序出现的最早位置开始枚举,遇到的第一个dfs序出现位置小于等于它,结束位置大于等于这三个节点最早结束位置的节点,就是我们要求的解,对于这个样例,l=3,r=9,代表4,5,3出现的最早和最迟位置,答案是1,因为L[1]=1<=3,R[1]=11>=9。
时间复杂度O(N)。
想答对这个题是非常简单的,建立一个大小为1000的小根堆就可以了。这个堆满足两个性质:
1.堆中的元素个数总是小于等于1000的
2.堆顶取出的元素总是这个堆里面最小的那一个
这样,这个题可以这样做:
priority_queue<int> q; while (cin>>n) { n=-n; //c++中默认优先队列是一个大根堆,因此把所有元素乘以-1就可以当小根堆用了 if (q.size()<1000) q.push(n); else { int t=q.top(); if (t>n) { q.pop(); q.push(n); } } }这个做法时间复杂度是O(Nlog(1000)),空间复杂度是O(1000),对于这个题来说已经非常快了大约是O(10n)。
二、一棵树节点1,
2, 3, ... , n. 怎样实现:先进行O(n)预处理,然后任给两个节点,用O(1)判断它们的父子关系
这个题目是DFS序的简单应用,首先来看看什么是DFS序,对于一棵树,有下面4条边:
1-2,1-3,2-4,2-5
那么,它的DFS序是:1,2,4,5,3,这里只是通过一次简单的深度优先搜索把每个节点访问的次序标了出来,如果每个节点在被访问的这一刻记录一次,访问结束的时候再记录一次,那又能是什么样子呢?代码是这样的:
int dfs(int i) { q.push_back(i); for (int j=0;j<edge[i].size();j++) if (!vis[edge[i][j]]) { vis[edge[i][j]]=1; dfs(edge[i][j]); } q.push_back(i); }
此时,上面这幅图,它的dfs序变成了:1,2,4,4,5,5,2,3,3,1。
观察这个序列,可以发现:节点i是节点j的祖先,当且仅当节点i出现的两个位置x1,x2在节点j出现的两个位置y1,y2的两边,也就是x1<y1<y2<x2。所以,在生成dfs序的时候顺便记录每个节点dfs序出现的位置,之后每读入一个询问,直接O(1)判断并输出就可以了。
三. 给定一个二叉树,求其中N(N>=2)个节点的最近公共祖先节点。
这道题跟上面那道题解法非常像,首先求出来dfs序,拿第二题为例,dfs序为1,2,4,4,5,5,2,3,3,1,此时,要求4,5,3三个节点的最近公共祖先,怎么求呢?直接从4,5,3dfs序出现的最早位置开始枚举,遇到的第一个dfs序出现位置小于等于它,结束位置大于等于这三个节点最早结束位置的节点,就是我们要求的解,对于这个样例,l=3,r=9,代表4,5,3出现的最早和最迟位置,答案是1,因为L[1]=1<=3,R[1]=11>=9。
时间复杂度O(N)。
相关文章推荐
- 笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数
- 笔试算法题(27):判断单向链表是否有环并找出环入口节点 & 判断两棵二元树是否相等
- 数据结构&算法面试题集中营____序言
- 【数据结构&&算法】树,支持无限子节点
- 笔试题&面试题:设计一个复杂度为n的算法找到单向链表倒数第m个元素
- 算法与数据结构面试题(11)-一次遍历得到链表的中间节点
- 算法与数据结构面试题(11)-求二叉树中节点的最大距离
- 判断浏览器类型&amp;获取DOM节点
- 算法面试题之判断整数是否可以被3整除
- 算法->判断单链表环的入口
- 这是网友发的一道很常见的面试题, for(foo('A');foo('B')&&(i<2);foo('C')) ,其实考的就是for (初始化语句; 判断条件; 循环条件) ,现在详细解析一下!
- 笔试题&面试题:设计一个复杂度为n的算法找到单向链表倒数第m个元素
- 零零散散学算法之判断集合的相同&相似性
- 笔试算法题(21):将stack内外颠倒 & 判断扑克牌顺子
- 数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点
- 【算法面试题】寻找二叉搜索树中两个节点的最近公共祖先节点(转)
- 笔试算法题(18):常数时间删除节点 & 找到仅出现一次的两个数字
- 括号配对:假设一个数学算式中包括圆括号"()",方括号”[]"和花括号“{}”三种类型,编写一算法判断表达式的括号是否配对。
- 算法_已知五个>=0的自然数,随机输入5个数,编写算法判断是否能排列成有序的数字。0可以替换成任何数
- C++算法之 求二叉树中叶子节点的个数 与 判断两棵二叉树是否结构相同