Uva1609:Boring的序列(有相当难度的好题!)
来源:互联网 发布:壁虎老师java百度云 编辑:程序博客网 时间:2024/06/01 08:34
这道题的意思是:给定一个序列,如果任意子序列里面都有至少一个不重复的元素(不重复是只在子序列里面是唯一的),那么我们就叫这个序列是不无聊的。我们需要检测一个序列是否满足这种性质。
这道题首先是有O(n^2)的解法的,枚举任意子区间然后判断,但是判断这个操作为O(n),我们需要将其降为O(1).方法是用滑动窗口来维护信息,并且时刻维护不重复元素的数量。当然这种方法很直观,但是效率太低。
考虑有没有O(NlogN)的算法呢?
接下来考虑一下动态规划呢?好像A[L][R]这样的结构也是决定了O(N^2)的复杂度。
最后考虑一下分治算法,怎么分治?我们分成两个子序列不是随便分的,要考虑分完之后我们完整的序列是不是满足这个性质,很显然加入两个子序列满足这个性质,那么完整序列不满足的唯一可能就是存在一个跨过中间的序列不满足这个性质,但是这样一来枚举这个中间序列的复杂度非常的高(O(N^2/4)),这还不如一开始的办法。我也是在这里卡住了。最后参考了一下解析:
我们不妨先确定整个序列是否满足这个条件,如果满足就一定可以找到一个a[p],a[p]是全局唯一,然后从p开始分成两部分。这样T(N) = T(N-p)+T(p)+O(寻找a[p])。然而问题又来了,最后p怎么找呢?如果寻找p的复杂度是O(n),那么极端情况下T(N) = T(N-1)+T(1)+O(N) = O(N^2).但是好像找到一个p肯定要至少n次。其实我们可以先预处理所有元素,找到每一个元素左右和他最近的元素的位置。这可以在O(n)的时间完成!然后从两边开始寻找这个p,每次检测一个元素在当前区间是不是唯一只要O(1),这样不管p在那里,最终的复杂度不会高于O(NlogN),极端情况甚至可能是O(N)!
最后怎么找p的左右区间?答案是用一个set从左往右遍历并保存即可。
总结:这道题还是有相当难度的,关键就在于找到一个p然后分治,而且p的找法也很特殊,说实话我是想不出这么巧妙的办法。也可以总结出来分治的关键是两点:如何分,如何治?先分后治,还是先治后分?这都是值得我们思考的问题!
def find_bound(a): n = len(a) window = {} pos_left,pos_right = {},{} for i,x in enumerate(a): if x in window: pos_left[i] = window[x] pos_right[window[x]] = i window.pop(x)#ensure the only ele in window window[x] = i return pos_left,pos_rightdef find_unique(a,bound_left,bound_right): global pos_left,pos_right def check(pos):# x is the position left,right = 0,0 left = pos_left[pos] if pos in pos_left else -1 right = pos_right[pos] if pos in pos_right else len(a) return left<bound_left and right > bound_right left,right = bound_left,bound_right while left<=right: if check(left):return left elif check(right):return right left+=1 right-=1 return Nonedef main(a,left,right): global pos_left,pos_right if left>=right:return True pos = find_unique(a,left,right) if pos==None:return False else: return main(a,left,pos-1) and main(a,pos+1,right)a = [1,4,3,2,0,3,2,1,3]pos_left,pos_right = find_bound(a)print('no-boring' if main(a,0,len(a)-1) else 'boring')
0 0
- Uva1609:Boring的序列(有相当难度的好题!)
- 相当好的客服管理软件
- 有难度的算法
- 有一定难度的程序题
- 一个有难度的Java笔试题
- 一道极其有难度的算法题!!!
- 一道颇有难度的JavaScript题
- 相当好的HTML5 抛砖引玉的文章
- 这个网站相当好喔,我很喜欢,有很多可以用的资源
- 一段有难度的程序
- 相当好的Perl中文教程
- 相当好的.NET正则大全2
- 一篇关于A*的文章相当好
- 一款相当好用的VPN软件
- 相当好用的Xcode插件管理软件
- jQuery 的serialize()相当好用
- 这有相当多的优势。
- 正则表达式入门教程(写的相当好,保证看完后对正则表达式有一个全面的认识)
- MySQL中myisam和innodb的主键索引有什么区别?
- oj-12-B-十进制转换成二进制
- 业余爱好者如何通过使用模板快速建站6(How do amateurs build their own websites with a template part-6)
- 外部js调用Angular控制器中的函数方法或变量用法示例
- 使用命令行将mysql数据库导入导出操作
- Uva1609:Boring的序列(有相当难度的好题!)
- 温故而知新:北桥和南桥
- 仿ios沉浸式头部
- GPCC升级3.0
- 十进制转二进制
- SpringMVC Date Bad request 解决办法
- 如何查看linux服务器磁盘的具体型号
- hadoop SecondNamenode详解
- React Native 中的 Android 原生模块