前言
“这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战”
- NC95 数组中的最长连续子序列(较难)
- NC37 合并区间(中等)
数组中的最长连续子序列
描述:给定无序数组arr,返回其中最长的连续序列的长度(要求值连续,位置可以不连续,例如 3,4,5,6为连续的自然数)
输入:[100,4,200,1,3,2]
返回值:4
思路分析: 首先对数组排序,排序之后就转换成动态规划的问题 dp[i] 代表以 i结尾最长连续子序列的长度 因为 dp[i] 只与 前一个不与当前元素相等的 元素 的 dp[j] 有关, 因此 可以使用一个变量 pre 记录 当前有序序列的长度
如果当前元素比前一个大1,说明他们可以构成连续的序列,pre++,如果相等就跳过,否则就不能构成连续的序列,pre重置为1
遍历的过程是 使用 ans 更新 最大值 ans = Math.max(ans, pre)
AC 代码:
public int MLS(int[] arr) {
// write code here
if (arr == null || arr.length == 0) {
return 0;
}
Arrays.sort(arr);
int pre = 1;
int ans = 1;
for (int i = 1; i < arr.length; i++) {
if(arr[i] == arr[i-1]){
continue;
}
if(arr[i] == arr[i-1] + 1){
pre++;
}else{
pre = 1;
}
ans = Math.max(ans, pre);
}
return ans;
}
合并区间
描述: 给出一组区间,请合并所有重叠的区间。 请保证合并后的区间按区间起点升序排列。
输入: [[10,30],[20,60],[80,100],[150,180]]
返回值: [[10,60],[80,100],[150,180]]
思路分析: 按照左侧区间从小到大排序, 左侧区间相等的情况下,按照右侧区间从大到小排序
针对与前两种情况 (B.start <= A.end) 新的区间 左侧不变为A.start 右侧为 B.end 与 A.end 的最大值
最后一种情况 不相交 添加即可
AC 代码:
public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
if (intervals == null || intervals.size() == 0) {
return new ArrayList<>();
}
Collections.sort(intervals, (a, b) -> a.start == b.start ? b.end - a.end : a.start - b.start);
ArrayList<Interval> ans = new ArrayList<>();
ans.add(intervals.get(0));
for (int i = 1; i < intervals.size(); i++) {
Interval cur = intervals.get(i);
Interval last = ans.get(ans.size() - 1);
if (cur.start == last.start) continue;
if (cur.start <= last.end){
ans.remove(last);
last = new Interval(last.start, Math.max(last.end, cur.end));
ans.add(last);
}else{
ans.add(cur);
}
}
return ans;
}