剑指 Offer II 074. 合并区间(56. 合并区间)
题目:
思路:
【1】错误的尝试
【2】不进行排序该如何正确的处理
【3】进行排序的处理
代码展示:
进行排序的处理:
//时间5 ms击败90.74% //内存44.4 MB击败16.45% //时间复杂度:O(nlogn),其中 n 为区间的数量。 //除去排序的开销,我们只需要一次线性扫描,所以主要的时间开销是排序的 O(nlogn)。 //空间复杂度:O(logn),其中 n 为区间的数量。这里计算的是存储答案之外,使用的额外空间。 //O(logn) 即为排序所需要的空间复杂度。 class Solution { public int[][] merge(int[][] intervals) { if (intervals.length == 0) return new int[0][2]; //这种是lambda表达式展开前的原本写法 // Arrays.sort(intervals,new Comparator<int[]>() { // public int compare(int[] interval1, int[] interval2) { // return interval1[0] - interval2[0]; // } // }); Arrays.sort(intervals, (intVal1, intVal2) -> intVal1[0] - intVal2[0]); List<int[]> merged = new ArrayList<int[]>(); for (int i = 0; i < intervals.length; ++i) { int L = intervals[i][0], R = intervals[i][1]; if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) { merged.add(new int[]{L, R}); } else { merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R); } } return merged.toArray(new int[merged.size()][]); } }
不进行排序该如何正确的处理:
//时间1 ms击败100% //内存43.9 MB击败86.6% class Solution { public int[][] merge(int[][] intervals) { int maxValue = 0; //遍历找到结束最大值 for (int i = 0; i < intervals.length; i++) { if (intervals[i][1] > maxValue) { maxValue = intervals[i][1]; } } maxValue++; //最大值加1 int[] startSide = new int[maxValue]; //根据最大值 创建数组,默认0 boolean[] help = new boolean[maxValue]; //根据最大值 创建数组,默认false for (int[] v : intervals) { //遍历二维数组,命中起始值该下标值设为1,每出现一次加1,命中结束值该下标值设为-1,每出现一次-1 startSide[v[0]] += 1; startSide[v[1]] -= 1; //为了防止起始值和结束值为同一个值 if (v[0] == v[1]) { //如果起始值=结束值,那么该位置赋值true help[v[0]] = true; } } ArrayList<int[]> ans = new ArrayList<>(); int startValue = -1; int endValue; int sumValue = 0; //累加值 for (int i = 0; i < maxValue; i++) { //遍历到最大值 if (startSide[i] != 0) { //当数值不为0时参与计算考虑,大于0为起始数字,小于0为结束数字,当和为0时那么一个闭合完成。 sumValue += startSide[i]; if (startValue == -1 && sumValue > 0) { //当没有起始数字时,且和值大于0说明第一次出现起始数字 startValue = i; } if (sumValue == 0) { //当和值等于0说明最后一次出现结束数字 endValue = i; ans.add(new int[]{startValue, endValue}); //重置起始数字 startValue = -1; } } else { if (help[i] && sumValue == 0) { ans.add(new int[]{i, i}); } } } return ans.toArray(new int[ans.size()][]); } }
错误的尝试:
class Solution { public int[][] merge(int[][] intervals) { LinkedList<int[]> result = new LinkedList<>(); int[] temp = null; for (int[] data : intervals){ if (temp == null) { temp = data; continue; } // 需要考虑的情况:要么是temp的最大值在data的区间内,要么是data的最大值在temp的区间内,都代表着两者重合 // 1.[1,4],[0,4] // 2.[2,3],[4,5],[6,7],[8,9],[1,10] // 3.[2,3],[5,5],[2,2],[3,4],[3,4] //这种无序的间隔着实难搞,不得不要进行排序 if ((temp[1] >= data[0] && temp[1]<= data[1]) || (data[1] >= temp[0] && data[1]<= temp[1])){ int min = Math.min(temp[0],data[0]); int max = Math.max(temp[1],data[1]); //针对情况2,进行向上合并 int[] last_arr = result.peekLast(); while (!result.isEmpty() && ((max >= last_arr[0] && max<= last_arr[1]) || (last_arr[1] >= min && last_arr[1]<= max))){ last_arr = result.pollLast(); min = Math.min(min,last_arr[0]); max = Math.max(max,last_arr[1]); } temp = new int[]{min,max}; continue; } result.add(temp); temp = data; } if (temp != null) result.add(temp); int[][] res = new int[result.size()][2]; for (int i = 0; i < result.size(); i++){ int[] data = result.get(i); res[i] = data; } return res; } }