LeetCode 435. 无重叠区间
题目链接:435. 无重叠区间 - 力扣(LeetCode)
思路:
画图,遇到重叠区间的时候就画图,其实关键就是先排序,lambda x : x[0],然后确保每一个区间的左边界大于等于前一个区间的右边界,如果前一个的右边界大于该左边界,则删除掉一个,剩一个右边界小的区间,这样和下一个比较时会更低的概率重合。
代码:
#python
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key = lambda x : x[0]) //按左边界来排序
count = 0 //初始化一个计数器
for i in range(1, len(intervals)): //从第二个开始
if intervals[i][0] < intervals[i - 1][1]: //判断两个边界
count += 1
intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]) //选择右边界尽量小的
return count
/java
import java.util.*;
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
if (intervals == null || intervals.length == 0) {
return 0;
}
// 按照左边界进行排序
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
int count = 0; // 初始化计数器
for (int i = 1; i < intervals.length; i++) {
// 判断两个区间的重叠情况
if (intervals[i][0] < intervals[i - 1][1]) {
count++; // 重叠区间数量增加
// 选择右边界尽量小的
intervals[i][1] = Math.min(intervals[i - 1][1], intervals[i][1]);
}
}
return count;
}
}
LeetCode 763. 划分字母区间
题目链接:763. 划分字母区间 - 力扣(LeetCode)
思路:
这道题其实还是比较难的,但是可以读出来确实是贪心的做法,卡哥教的做法比较巧妙,我们通过一个hashmap来存该字母出现最晚的位置,然后初始化一个左边界begin,与一个右边界end来每次确定每次划分区间的长度,那么在两个区间中不断比较每个数的最晚位置,使得右边界end是该区间的最大数,不会漏掉数没计算。最后计算end -begin + 1来存入列表中(因为结果要求用列表返回)。这样就可以在不破坏原始顺序的情况下返回最多片段数的划分办法了。
代码:
#python 贪心算法
class Solution:
def partitionLabels(self, s: str) -> List[int]:
res = []
begin, end = 0, 0 //左右边界
hashmap = {} //用hashmap来存当前字母在串中出现的最晚位置
for i in range(len(s)):
hashmap[s[i]] = max(hashmap.get(s[i], -1), i) //实现
while begin < len(s): //用左边界来判断
end = hashmap[s[begin]] //先初始化一个end,从第一个开始
i = begin + 1 //i就是begin后面开始用来遍历的下标
while i < end: //如果还没追上右边界,继续
end = max(hashmap[s[i]], end) //不断地更新右边界,以保证其最大
i += 1 //挪到下一个
res.append(end - begin + 1) //左闭右开,如果不+1,就把左边闭的位置给漏掉了
begin = end + 1 //挪一下,把begin位置放到当前end的后一个,为下一轮做准备
return res //返回结果
/java
import java.util.*;
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> res = new ArrayList<>();
int begin = 0, end = 0;
Map<Character, Integer> hashmap = new HashMap<>();
// 构建哈希表,记录每个字符在字符串中最后出现的位置
for (int i = 0; i < s.length(); i++) {
hashmap.put(s.charAt(i), Math.max(hashmap.getOrDefault(s.charAt(i), -1), i));
}
while (begin < s.length()) {
// 初始化end为当前字符最后出现的位置
end = hashmap.get(s.charAt(begin));
// 寻找当前划分内的最远边界
for (int i = begin + 1; i < end; i++) {
end = Math.max(end, hashmap.get(s.charAt(i)));
}
// 将当前划分的大小添加到结果列表中
res.add(end - begin + 1);
// 移动begin到下一个划分
begin = end + 1;
}
return res;
}
}
LeetCode 56. 合并区间
题目链接:56. 合并区间 - 力扣(LeetCode)
思路:
上一道题能理解的话这道题是比较简单的,两个条件,互不重叠切全部覆盖,也就是说本来重叠的两个区间,我们取最小的边界与最大的边界即可满足条件。
代码:
#python
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key = lambda x : x[0]) //同样的,用左边界来排序
merged = [] //题目要求返回区间
for interval in intervals: //遍历每一个
if not merged or merged[-1][1] < interval[0]: //如果与前一个不重叠,直接append
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][-1], interval[1]) //否则我们直接修改一下右边界,注意,就别再添加了
return merged
/java
class Solution {
public int[][] merge(int[][] intervals) {
// 按照区间的起始位置进行排序
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
List<int[]> res = new ArrayList<>();
// 将第一个区间添加到结果列表中
res.add(intervals[0]);
for (int i = 1; i < intervals.length; i++) {
// 获取结果列表中的最后一个区间
int[] lastInterval = res.get(res.size() - 1);
// 如果当前区间的起始位置大于最后一个区间的结束位置,则它们是独立的,可以直接添加到结果列表中
if (intervals[i][0] > lastInterval[1]) {
res.add(intervals[i]);
} else {
// 否则,需要合并这两个区间
// 更新最后一个区间的结束位置为两者中的较大值
lastInterval[1] = Math.max(lastInterval[1], intervals[i][1]);
}
}
// 将结果列表转换为二维数组
int[][] mergedIntervals = new int[res.size()][2];
for (int i = 0; i < res.size(); i++) {
mergedIntervals[i] = res.get(i);
}
return mergedIntervals;
}
}