算法导论 最大重叠点问题

sunnyplain 2009-04-08 01:17:30
算法导论中文版(原书第二版)190页思考题14-1
假设希望对一组区间记录一个最大重叠点,亦即覆盖它的区间最多的那个点。
a)证明:最大重叠点总存在于某段的端点上。
b)设计一数据结构,能有效地支持操作INTERVAL-INSERT,INTERVAL-DELETE和返回最大重叠点操作FIND-POM。(提示:将所有端点组织成红黑树。左端点关联+1值,而右端点关联-1值。附加一些维护最大重叠点的信息以扩张树中结点。)

问题a)容易证明。设P为最大重叠点,那么P左边的一个端点肯定是某个区间的左端点,否则的话该端点的左邻域中的点重数会大于P的重数。同理可证P右边的一个端点肯定为右端点。并且这两个端点和P有相同的重数。
问题b)我希望能设计一个数据结构,对于INTERVAL-INSERT,INTERVAL-DELETE和FIND-POM三种操作,都能在O(lgn)时间内完成。
否则的话可以有更慢的方法。每个区间的左右端点各当成一个关键字(但分别关联+1和-1),将所有这些关键字组织成红黑树,那么INTERVAL-INSERT和INTERVAL-DELETE操作可以在O(lgn)时间完成,用中序遍历的方法FIND-POM在O(n)时间也能完成。
...全文
936 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2009-07-10
  • 打赏
  • 举报
回复
学习中.基本上dlyme给我了很大的启发,dlyme给的算法是针对于静态区间完成的,就是先将endpoints排一次序然后left endpoints就+1,right endpoints就-1然后求解某个点的最大值.但是dlyme开始给出的算法并不是书中问题的方法,因为书中区间是动态插入和删除的.不过一旦知道了静态区间的方法之后就可以很容易通过扩展平衡树来解决动态区间的问题,所以基本上dlyme应该给很多分
sunnyplain 2009-04-13
  • 打赏
  • 举报
回复
那你的意思是不是模仿顺序统计树,对结点x,令l[x]记录以x为根的子树中的小于x的左端点个数,r[x]记录右端点个数,这样对任意结点x,就可在O(lgn)时间内确定它的区间重叠数了,但如果想知道所有的区间的最大重叠数,是不是还要遍历整棵树呢?
  • 打赏
  • 举报
回复
前面已经讨论过:对于已经排过序的2n个端点,只要遍历一遍,就可以得到每个端点对应的重叠区间个数(从而也能得到最大重叠点);

来看顺序统计树,它的特点就是能够在logn时间内得到任一元素的顺序统计量(属于第几大元素)。
只要把这个稍微加以修改(假设在小于它的元素中,左端点个数是L、右端点个数是R,那么L-R+1就是它对应的重叠区间个数),所以对任意元素的插入、删除、查找(重叠区间个数)都能在logn内完成。

再开帖就不必了,交流而已,分数不是那么要紧~
sunnyplain 2009-04-13
  • 打赏
  • 举报
回复
不好意思,对于8L和13L的回复还是看不懂
[Quote=引用 8 楼 dlyme 的回复:]
……
在顺序统计树的基础上修改一下:对某结点x来说,不光记录它在树中是第几大的元素,同时还记录下所有比它小的节点关联值总和(再加一)。

[/Quote]
这句话指的都是以x为根的子树吧,否则无法在O(lgn)时间内维护吧,但是这又和最大重叠点有什么关系呢?

[Quote=引用 13 楼 dlyme 的回复:]
……
同样的道理,我们可以再增加两个域:记录子树中左端点的数量和右端点的数量,这样插入节点和顺序统计(分别统计小于新插入端点值的左、右端点数量)都能在logn内完成,同时也完成了调节最大重叠点的工作。
[/Quote]
对结点x,记录以x为根的子树中左端点和右端点的数量怎么推导出最大重叠点呢?

如果真的是正确的话,可以再建一帖来给剩下的分数中的绝大部分
  • 打赏
  • 举报
回复
奇怪,按我8L说的也可以实现,为什么被楼主无视了?

普通的顺序统计树,是在红黑树节点中多加了一个域来记录以本节点为根的子树中的节点数量。
借助这个添加的域,能够在logn内时间内完成顺序统计。
同样的道理,我们可以再增加两个域:记录子树中左端点的数量和右端点的数量,这样插入节点和顺序统计(分别统计小于新插入端点值的左、右端点数量)都能在logn内完成,同时也完成了调节最大重叠点的工作。
  • 打赏
  • 举报
回复
类似11L中提到的方法,插入节点之后并不需要遍历整棵树,而是增量调节一些(不会超过O(logn)规模)节点对应的最大重叠点(类似o[x]和m[x])信息即可
sunnyplain 2009-04-13
  • 打赏
  • 举报
回复
所谓明辨是非嘛,说多点也很好的
不过好像即使搜索以x为根的子树中的最大重叠点,也要遍历以x为根的子树吧,这样也不是O(lgn)的时间
  • 打赏
  • 举报
回复
如果“只记录以x为根的子树中的左右端点数量”,能够在logn时间内查找任意端点对应的重叠区间数量;
如果Find-Pom的意思是要直接返回最大重叠点,那么只需要在此基础上增加对“最大重叠点”信息的记录和更新维护(实际上就是11L说的O(x))就可以了.

打住打住,忍不住又多说了~
sunnyplain 2009-04-13
  • 打赏
  • 举报
回复
呵呵
不过我觉得只记录以x为根的子树中的左右端点数量好像没办法在O(lgn)时间内得到所有区间的最大重叠数
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 dlyme 的回复:]
同样的道理,我们可以再增加两个域:记录子树中左端点的数量和右端点的数量...
[/Quote]
不是直接记录比x小的左、右端点数量,而是记录以x为根的子树中的左、右端点数量(这和顺序统计树的道理是一样的,记录的是以x为根的子树节点数量(而不是直接记录比x小的节点数量),但以此为根据能迅速计算出x是第几大元素)。

我留神看了一下11L的内容,其实是一样的道理,11L说的其实还是一颗顺序统计树(如果我们还喜欢用顺序统计树这个概念的话)。
也许是我表达得不够清楚(实际上我确实没有注意到o[x]这个概念),一直没有提到点子上。但问题已经解决了,就到这里吧,再说下去更描述不清了。

copperybean 2009-04-12
  • 打赏
  • 举报
回复
感谢dlyme一直关注该帖,所以不忍无满意结帖;但问题没有解决,所以我觉得不能给全部分。所以只能用我的另一个账号来接分,还望大家谅解
sunnyplain 2009-04-12
  • 打赏
  • 举报
回复
第二个公式提交以后变样了,应该是:


m[left[x]] (o[x]就是o[left[x]])
m[x] = max v[left[x]] + p[x] (o[x]就是x)
v[left[x]] + p[x] + m[right[x]] (o[x]就是o[right[x]])
sunnyplain 2009-04-12
  • 打赏
  • 举报
回复
看来是求人不如求己啊,在原书作者写的笔记《Introductor's Manual》中找到了答案

构造这样一颗红黑树,将每个区间的端点当成一个关键字,假设有n/2个区间,那么树中有n个关键字。如果结点x对应一个区间的左端点,则令q[x]为1,否则为-1;另外假设ei,……,ej为中序遍历以x为根的子树的关键字序列,那么令v[x]=p[ei]+……+p[ej];定义o[x]为以x为根的子树中的一个关键字ek,使得p[ei]+……+p[ek]为最大,并定义m[x]为这个和。那么有如下关系:
v[x]=v[left[x]]+p[x]+v[right[x]]

m[left[x]] (o[x]就是o[left[x]])
m[x] = max v[left[x]] + p[x] (o[x]就是x)
v[left[x]] + p[x] + m[right[x]] (o[x]就是o[right[x]])

由书中定理14.1可知插入和删除操作中维护这些域只需O(lgn)时间,而FIND-POM就对应于值o[root[T]]

这里只是照原文进行简单翻译,如需详细论证,请参看原文
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sunnyplain 的回复:]
这两个方法是一样
但题目(题目是我照原文一字不差抄下来的)中提到了INTERVAL-INSERT操作,那么就应该意味着区间可能不是一次全部给出的,需要提供插入操作,当插入一个区间后要能在O(lgn)时间内保持数据结构的性质。
[/Quote]
那原题的意思可能是要这样:
在顺序统计树的基础上修改一下:对某结点x来说,不光记录它在树中是第几大的元素,同时还记录下所有比它小的节点关联值总和(再加一)。
这样插入、更新最大重叠点信息都可以在logn时间内完成~
sunnyplain 2009-04-12
  • 打赏
  • 举报
回复
宏观思路应该是这样
顺序统计树每个结点x记录的是以x为根的子树中的结点个数,但是我不知道这里应该记录什么信息,才能达到题目中的要求
这个记录的信息在插入和删除操作中必须能在O(lgn)时间内被正确更新
sunnyplain 2009-04-10
  • 打赏
  • 举报
回复
这两个方法是一样
但题目(题目是我照原文一字不差抄下来的)中提到了INTERVAL-INSERT操作,那么就应该意味着区间可能不是一次全部给出的,需要提供插入操作,当插入一个区间后要能在O(lgn)时间内保持数据结构的性质。
  • 打赏
  • 举报
回复
1.
[Quote=引用 3 楼 sunnyplain 的回复:]
另外有一句“该区间在S中的(顺序统计)位置”,要实现这句话要遍历树才能做到吧
[/Quote]
这正是顺序统计树的优点所在,能够在logn之内完成,所以整个算法不会超过O(n*logn)

2.这个问题的最大重叠点一定出现在端点上。更进一步说,它一定可以出现在左端点上。
由于已经对2n个端点进行过排序,所以在S中只记录个数就可以了,的确象你说的“再顺序遍历一次就行了,也用不着树”。
上面提的那个算法实际上受以前一些问题的影响,没有仔细考虑。排序之后简单得多,遍历一遍后就出结果了。

3.我不知道你这里说的“INTERVAL-INSERT,INTERVAL-DELETE和FIND-POM”究竟是什么意思。
可能我看的版本不同,原题里只是要求出“最大重叠点”,没有其它要求。
不管怎样来说,对于这道题不会再找到比O(n*logn)更快的法子了~
  • 打赏
  • 举报
回复
这题我不知道到底要考察什么~

如果将所有端点组织成红黑树(左端点关联+1值,而右端点关联-1值),最后中序遍历一遍,加加减减就能得到最大重叠点了。但这种方法和上面提到的方法本质上是完全一样的。
sunnyplain 2009-04-10
  • 打赏
  • 举报
回复
我也觉得O(nlgn)是最快了
我认为原题是的意思是“要处理的区间不是一次就全部给出的”,可能先给了你n个区间,如果你按上面的方法搞定了,那么接下来再给一个区间,如果按上面方法,那就要完全重做一遍。也就是每次多增加一个区间都要付出O(nlgn)的时间。
单考虑顺序统计树,每次插入一个新的关键字需要O(lgn)时间,同时确定该关键字的秩也只需要O(lgn)时间,而上面算法当需要插入一个新的区间的时候,全部事情都要重做一遍。
sunnyplain 2009-04-09
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dlyme 的回复:]
这应该是对应“顺序统计树”的一道习题吧~

首先将n个区间的2n个端点从小到大排序;
用一个集合S(顺序统计树,集合中的元素以区间左端点的大小为序)来记录当前发生重叠的区间,初始化S为空;
遍历2n个端点
{
如果该点为某区间左端点
{
将对应区间加入S中;
该区间在S中的(顺序统计)位置,就是该(左端)点对应的重叠个数,如有必要则更新最大重叠个数;
}
如果该点为某区…
[/Quote]

感觉有问题
不知道这里的树对于INTERVAL-INSERT,INTERVAL-DELETE和FIND-POM操作有什么意义,好像这里的树只能实现FIND-POM操作。
我觉得INTERVAL-INSERT操作的意思应该是可能先给n个区间,等一下再给你一个区间让你插进来,并可以更新最大重叠点,上面的方法好像没法做到这个。
其实如果只是想在O(n*lgn)时间内实现FIND-POM操作的话,只要将2n个端点排序,再顺序遍历一次就行了,也用不着树。
另外有一句“该区间在S中的(顺序统计)位置”,要实现这句话要遍历树才能做到吧,所以这个方法在O(nlgn)时间内搞不定吧。
加载更多回复(2)

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧