LeetCode 56, Merge Intervals 从 TLE 到 AC
2015-07-30 22:15
369 查看
LeetCode 56, Merge Intervals 从 TLE 到 AC
这个题再次告诉我,光照着API或者java docs 写代码是靠不住的,还是要去看底层的源代码。前人封装好的黑盒子给我们用,并不是照着说明书做就可以了,有时候还需要知道黑盒子里大概装的是什么。https://leetcode.com/problems/merge-intervals/
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
[code]/** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ public class Solution { public List<Interval> merge(List<Interval> intervals) { } }
这道题本身的思路很明确。先按照Interval.start 排序,然后合并重叠的部分。排序的时间复杂度是O(n*log(n)), 合并是O(N)。 List类下面有一个 sort 方法,既然是做leetCode, 我觉的这题的难点也就是排序了,于是就像自己再写一遍quickSort算法。另外,出于节省空间的目的,我的想法是,在传入的List〈Intervals〉上进行sort 和 merge 而返回新的List对象。
于是,我写了sort 方法,并在 sort 之后对 传入的List参数进行merge 操作,代码如下:
[code] public void quickSort(List<Interval> intervals,int h, int t){ //print(intervals); int i=h+1; int ref=intervals.get(h).start; for(int j=h+1;j<t;j++){ //System.out.println(j); if(intervals.get(j).start < ref){ swap(intervals,j,i); i++; } } swap(intervals,h,i-1); if(i>h+1) quickSort(intervals,h,i); if(t>i+1) quickSort(intervals,i,t); }
然后,我对sort 后的代码,进行merge 操作:
[code] quickSort(intervals,0,size); //merge Interval cur=intervals.get(0); int start=cur.start, end=cur.end; for(int i=1;i<size;i++){ Interval it=intervals.get(i); //System.out.println("size:"+size+" i:"+i); //print(intervals); if(end>=it.start){ intervals.remove(i-1); intervals.remove(i-1); end=Integer.max(end,it.end); Interval tmp=new Interval(start,end); intervals.add(i-1,tmp); i--; size--; }else{ start=it.start; end=it.end; } }
以上代码虽然不够clean,草草写出来的,但是我想O(n*log(n))的算法,肯定是可以通过所有test cases 的,结果恰恰出乎我意料,没有AC,而是TLE了。这题既然要排序,就肯定是这个O(n*log(n))的复杂度,一定是我的算法复杂度计算错了。那么哪里不对呢?
很快便想到,是java.util.List 下的add 方法和 remove 方法本身的复杂度并不为O(1)。
util.ArrayList 相关源码如下:
[code] public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1,size - index); elementData[index] = element; size++; }
这里可以看到,引用了lang.System.arraycopy
[code] public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
很遗憾,arraycopy是一个native方法,应该是C/C++ 实现的,看不到进一步的源码了。但是没关系,我在注释里找到了这句话:
[code]A subsequence of array components are copied from the source * array referenced by <code>src</code> to the destination array * referenced by <code>dest</code>. The number of components copied is * equal to the <code>length</code> argument.
这说明,arraycopy其实是把每一个element 往前copy一位,也就是说,这个操作的复杂度是O(n)而不是常数,这就印证了我的想法。
这个题再次告诉我,光照着API或者java docs 写代码是靠不住的,还是要去看底层的源代码。前人封装好的黑盒子给我们用,并不是照着说明书做就可以了,有时候还需要知道黑盒子里大概装的是什么。
相关文章推荐
- 主流编程网站
- TortoiseGit(乌龟git)保存用户名密码的方法
- Oracle 中merge into不能更新on中的字段
- 运算符重载的一些问题集锦
- 谷歌搜索替代方案
- 第72讲:Scala界面事件处理编程实战详解学习笔记
- HDU Can you solve this equation?
- Hibernate-note02
- IOS 创建含有category的静态库,selector not recognized的解决方案
- Android 多媒体开发学习之撕衣服
- ajax提交form表单
- hdu 5305(爆搜+二染色) Friends
- Mac和IOS下使用OpenCV
- 数据库知识总结
- SQL注入漏洞
- Linux 网卡驱动学习(四)(缓存描述符 Buffer Description)
- iOS开发:StoryBoard 使用Block在两个界面之间传值
- 能被2、3、4、5、6、7、8、9、10等数整除的数的特征
- app store怎么用支付宝充值
- HDU 3420 Bus Fair [补]