这道题思路直接,但bug free需要费些心力。第一版未优化的代码笔记长,未贴。
下面给出的两个实现,实现1是使用二分法找到新区间应插入的位置,然后检查是否需要和上一个区间合并(容易忽略),最后同后面的区间逐个检查是否需要合并。无需额外空间,Code Ganker 指出这种做法严格上非O(N),因为合并时有数组remove操作,最坏情况下是O(N^2),但跑leetcode测试用例这种实现比实现2效率高。
实现2:代码非常简洁,需要使用额外空间。先跳过新区间无交集且在新区间前面的,然后merge 和新区间有交集的,最后加上剩余的。
[ref]
http://blog.csdn.net/linhuanmars/article/details/22238433
http://blog.csdn.net/kenden23/article/details/17264441
/** * 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 { // Method 2: 使用额外空间,Time:O(N) public List<Interval> insert2(List<Interval> intervals, Interval newInterval) { List<Interval> result = new ArrayList<Interval>(); int i = 0; int N = intervals.size(); while (i < N && newInterval.start > intervals.get(i).end) { result.add(intervals.get(i++)); } if (i < N) { newInterval.start = Math.min(newInterval.start, intervals.get(i).start); } while (i < N && newInterval.end >= intervals.get(i).start) { newInterval.end = Math.max(newInterval.end, intervals.get(i++).end); } result.add(newInterval); while (i < N) { result.add(intervals.get(i++)); } return result; } // Method 1: 二分法查找插入位置,无额外空间 public List<Interval> insert(List<Interval> intervals, Interval newInterval) { if (intervals == null || intervals.size() == 0) { List<Interval> result = new ArrayList<Interval>(); result.add(newInterval); return result; } int N = intervals.size(); int i = findInsertPos(intervals, newInterval.start); // 判断是否需要和前一个区间merge if (i > 0 && intervals.get(i - 1).end >= newInterval.start) { newInterval.start = intervals.get(i - 1).start; newInterval.end = Math.max(newInterval.end, intervals.get(i - 1).end); intervals.remove(--i); } intervals.add(i, newInterval); i++; // 合并同newInterval有交集的区间 while (i < intervals.size() && newInterval.end >= intervals.get(i).start) { newInterval.end = Math.max(newInterval.end, intervals.get(i).end); intervals.remove(i); } return intervals; } public int findInsertPos(List<Interval> intervals, int target) { int left = 0, right = intervals.size() - 1; int mid = 0; while (left <= right) { mid = left + ((right - left) >> 1); Interval curr = intervals.get(mid); if (curr.start == target) return mid; else if (curr.start > target) right = mid - 1; else left = mid + 1; } return left; } }