736.划分字母区间
给你一个字符串 s
。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s
。
返回一个表示每个字符串片段的长度的列表。
提示:
1 <= s.length <= 500
s
仅由小写英文字母组成
思路
这题我自己没想出来,刚开始想的是遍历每个字母,遍历到了就加进哈希表,然后从后往前找第一个重复字母,然后再找下一个字母,但是始终没想明白怎么判断结束。
题解的思路是定义一个end来存储当前区间的结束位置,每次遍历判断end后面是否有和前面字母重复的,有的话就更新end,如果遍历到end就把当前区间长度加入答案。
还用到了一个技巧就是定义一个存放26个字母最后出现位置的数组,然后从前往后遍历数组,更新每个字母最后出现的位置,这样之后我们在遍历时就不需要再去从后往前找第一个重复字母。
代码
java
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> ans=new ArrayList<>();
int[] last=new int[26];
for(int i=0;i<s.length();i++){
last[s.charAt(i)-'a']=i;
}
int start=0,end=0;
for(int i=0;i<s.length();i++){
end=Math.max(end,last[s.charAt(i)-'a']);
if(i==end){
ans.add(end-start+1);
start=end+1;
}
}
return ans;
}
}
56.合并区间
以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
思路
看到这种区间类的题目我的第一反应是先排序,这里不用管相同的时候第二个元素怎么排,反正肯定会合并为一个区间。然后遍历,记录start和end作为合并的区间,首先初始化为[0][0]和[0][1],然后往后遍历,如果遍历到的元素的start小于等于当前的end,则更新end为该元素end与当前end之间较大值,如果大于则将当前start和end加入答案,并更新start和end为该元素的。若已经遍历到最后一个元素,则在处理完之后将start和end再加入答案。
代码
java
class Solution {
public int[][] merge(int[][] intervals) {
if(intervals.length==1){
return intervals;
}
List<int[]> ans=new ArrayList<int[]>();
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0]-o2[0];
}
});
int start=intervals[0][0],end=intervals[0][1];
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]<=end){
end=Math.max(end,intervals[i][1]);
}else {
ans.add(new int[]{start,end});
start=intervals[i][0];
end=intervals[i][1];
}
if(i==intervals.length-1){
ans.add(new int[]{start,end});
}
}
return ans.toArray(new int[ans.size()][]);
}
}
总结
最近几天的刷题有点刷上瘾了,这种自己独立思考写出代码然后ac的感觉确实很棒,后天就要进入动态规划了,希望不被虐死吧