汇总区间
做题过程
主要是怎么处理输出比较麻烦,本身没有什么算法。
算法概述
原题
本题要求为将给出的整数数组汇总为一些连续区间。只需要一次遍历即可。
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { public List<String> summaryRanges(int[] nums) { List<String> ret=new ArrayList<String>(); int i=0; int n=nums.length; while(i<n){ int low=i; i++; while(i<n&&nums[i]==nums[i-1]+1){ i++; } int high=i-1; StringBuffer temp=new StringBuffer(Integer.toString(nums[low])); if(low<high){ temp.append("->"); temp.append(Integer.toString(nums[high])); } ret.add(temp.toString()); } return ret; } }
|
总结
这种题目主要在于能不能熟练使用StringBuffer
这样的类(如果是C++就应该使用vector<string>
,以及如何组织代码结构。
插入区间(medium)
做题过程
肯定是模拟,但感觉分类讨论蛮多的,需要一些其他技巧进行优化。
算法概述
原题
本题要求为给定一个区间以及一个区间为元素的升序数组,插入给定区间(重叠则合并)。
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class Solution { public int[][] insert(int[][] intervals, int[] newInterval) { int left = newInterval[0]; int right = newInterval[1]; boolean placed = false;
List<int[]> ansList = new ArrayList<int[]>();
for (int[] interval : intervals) { if (interval[0] > right) { if (!placed) { ansList.add(new int[]{left, right}); placed = true; } ansList.add(interval); } else if (interval[1] < left) { ansList.add(interval); } else { left = Math.min(left, interval[0]); right = Math.max(right, interval[1]); } } if (!placed) { ansList.add(new int[]{left, right}); } int[][] ans = new int[ansList.size()][2]; for (int i = 0; i < ansList.size(); ++i) { ans[i] = ansList.get(i); } return ans; } }
|
总结
分类如下:
- 当前遍历区间在目标区间右侧(无并集):插入目标区间以及当前遍历区间
- 当前遍历区间在目标区间左侧(无并集):只插入当前遍历区间
- 当前遍历区间与目标区间重叠(有并集):由比较得出新的区间再插入
除此之外,还需注意处理在末尾插入的情况,因为第二个分类并不处理尾部插入的逻辑,所以这里需要一个 标记哨兵 。
用最少数量的箭引爆气球
做题过程
还是排序以及合并区间的问题。
算法概述
原题
本题要求为计算需要多少个元素能够代表所有区间(重叠的区间可以用一个相同的值来代表)。需要运用的是 排序以及贪心 。
- 时间复杂度为O(nlogn):主要是排序
- 空间复杂度为O(logn):容器类排序所需要的栈空间
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { public int findMinArrowShots(int[][] points) { if(points.length==0) return 0;
Arrays.sort(points, new Comparator<int[]>(){ public int compare(int[] point1,int[] point2){ if(point1[1]>point2[1]) return 1; if(point1[1]<point2[1]) return -1; else return 0; } }); int pos=points[0][1]; int ans=1; for(int[] balloon: points){ if(balloon[0]>pos){ pos=balloon[1]; ++ans; } } return ans; } }
|
总结
对于数字相关的问题,需要熟练掌握自定义比较器相关的方法。区间相关问题的优化路径在于在排序后如何省去多余的边界比较,比如此处就不再需要比较右边界,如何 分工 左右边界是需要思考与理解的。