持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情
題目:
- 给定一个数组,数组中包含若干个区间的集合,请合并并返回一个不重叠的区间数组,改数组中刚好覆盖输入中的所有区间。
- 字符串
s由小写字母组成。现要求将这个字符串划分成尽可能多的片段,使得每个字母只出现在一个片段。
解题思路
合并区间:
本题和之前插气球以及无重叠区间很像,在对数组进行操作之前,首先需要对数组进行排序,排序完成后就可以根据正常思路进行分析了。
重叠区间是当前区间的第一个数字小于等于前一个区间的第二个数字,那么我们只需要根据这个思路不断判断并且更新当前区间就行了,为了便于计算,此处以数组第二个区间作为起始点,依次遍历更新当前区间,如果大于则直接将前一个区间记录下来,这样遍历到数组末尾就能更新完所有数组。
但我们在累加结果的时候会遗漏最后一个区间,手动添加即可。为什么最后一个区间必然是不会和其余区间重合?这是因为如果最后一个区间和前一个区间重合,更新的也是最后一个区间的,而如果没重合,那更显而易见了。
可得代码如下:
public int[][] merge(int[][] intervals) {
ArrayList<int[]> list = new ArrayList<>();
if(intervals.length==1) return intervals;
Arrays.sort(intervals, (a, b)->{
if(a[0]==b[0]) return a[1]-b[1];
return a[0]-b[0];
});
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]<=intervals[i-1][1]){
intervals[i][0] = intervals[i-1][0];
intervals[i][1] = Math.max(intervals[i][1], intervals[i-1][1]);
}else {
list.add(intervals[i-1]);
}
}
list.add(intervals[intervals.length-1]);
return list.toArray(new int[0][]);
}
划分字母区间:
本题的思路是首先找到首字母的最后一个元素,之后依次遍历,直到首字母的最后一个元素之后的字母的最后一个元素找到就是一个结果。再次更新首字母即可。
难点就是记录每个元素的最后一个元素的位置,此处使用的是26位数组记录,可得代码如下:
public List<Integer> partitionLabels(String s) {
ArrayList<Integer> list = new ArrayList<>();
int[] digit = new int[26];
char[] c = s.toCharArray();
for(int i=0;i<c.length;i++){
digit[c[i]-'a'] = i;
}
int max = 0;
int last = -1;
for(int i=0;i<c.length;i++){
max = Math.max(max, digit[c[i]-'a']);
if(i==max){
list.add(i-last);
last = i;
}
}
return list;
}