「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」。
题目:给定一个二维数组,二维数组中包含的是若干区间的集合,要求合并此二维数组中所有的重叠区间,并且最终返回一个不重叠的区间数组,并且该数组需要刚好可以覆盖输入数据的所有区间。
解题思路
该题的关键是理解什么样的数据是最终可以合并的数据,例如数组[1, 3]和[2, 4],这最终结果显然是[1, 4],合并的过程是判断2小于3,则必定可以合并,但合并后的右界则是取决于max(3, 4),因此最终结果是[1, 4]。那么如果数组输入是[2, 4]和[1, 3]呢?此时就不好判断了,因此在对数组进行合并时,首先应该考虑的是对数组排序,排序规则是按照数组第一个元素从小到大排序,这样就可以顺序判断。而对于循环到的数据的左元素不小于已存入数据的最右元素的数据,则必定无法进行合并区间,此时则作为新的区间加入,但题目最终要求输出的是数组,因此最终将list转为数组即可,代码如下:
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
ArrayList<int[]> merge = new ArrayList<>();
for(int i=0;i<intervals.length;i++){
int L=intervals[i][0], R=intervals[i][1];
if(merge.isEmpty()||merge.get(merge.size()-1)[1]<L){
merge.add(new int[]{L, R});
}else {
merge.get(merge.size()-1)[1] = Math.max(merge.get(merge.size()-1)[1], R);
}
}
return merge.toArray(new int[merge.size()-1][]);
}
此处需要注意的是如何将ArrayList转为数组,上述代码时间复杂度为,空间复杂度为。代码总耗时为6ms,击败85%的Java提交用户。
最后
实际上本题就是一个贪心的思想,通过对一个一个子问题进行测试解决,通过子问题的局部最优,最终得到全局最优。贪心算法的解决就是通过直觉,感觉对了,那最后的代码大概率能写出来,难的是思路,感觉只能通过大量的练习来锻炼了。