56.合并区间
class Solution {
public int[][] merge(int[][] intervals) {
// 先按照区间的左端点进行排序
Arrays.sort(intervals, (a,b)->a[0]-b[0]);
List<int[]> ans = new ArrayList<>();
// 遍历每个区间
for(int[] inter : intervals){
int m = ans.size();
// 区间合并的情况,ans中有区间,且最后一个区间的右端点值>=当前区间的左端点值
if(m>0 && inter[0] <= ans.get(m-1)[1]){
// 更新右端点值
ans.get(m-1)[1] = Math.max(ans.get(m-1)[1],inter[1]);
}else{
// 加入新的区间,不需要合并
ans.add(inter);
}
}
return ans.toArray(new int[ans.size()][2]);
}
}
41.缺失的第一个正数
注意:题干要去空间复杂度为常数,因此我们可以借助原本的数组。
实际上,对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中。因为如果 [1,N] 都出现了,那么答案是 N+1,否则答案是 [1,N]中没有出现的最小正整数。
要么采用打标记的方式,要么采用置换的方法。这里我采用的是通过置换将数组恢复成[1, 2, ..., N] 的形式,但其中有若干个位置上的数是错误的,每一个错误的位置就代表了一个缺失的正数。
步骤:对数组进行一次遍历,对于遍历到的数 x=nums[i],如果 x∈[1,N],交换 nums[i]和 nums[x−1],这样 x 就出现在了正确的位置。在完成交换后,新的 nums[i]\ 可能还在[1,N] 的范围内,需要继续进行交换操作,直到 x∉[1,N]。
注意到上面的方法可能会陷入死循环。如果 nums[i]恰好与 nums[x−1] 相等,那么就会无限交换下去。因此出现这种情况,我们可以跳出循环,开始遍历下一个数。
由于每次的交换操作都会使得某一个数交换到正确的位置,因此交换的次数最多为 N,整个方法的时间复杂度为 O(N)。
class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;
// 恢复数组
for(int i=0; i<n; i++){
while(nums[i]>0 && nums[i]<=n && nums[nums[i]-1] != nums[i]){
int temp = nums[nums[i]-1];
nums[nums[i]-1] = nums[i];
nums[i] = temp;
}
}
// 找到第一个错误的位置
for(int i=0; i<n; i++){
if(nums[i] != i+1){
return i+1;
}
}
return n+1;
}
}