lc.41 缺失的第一个正数(字节真题)
题目描述
给一个无序数组nums,找出其中没有的最小正整数
时间复杂度要求为O(n),空间复杂度要求为O(1)
nums长度为n
思路
1. 建哈希表
遍历一遍数组,把为正整数的都放入哈希表中,最后从0 ~ n遍历哈希表的key,找到不存在于哈希表中的key,就是目标答案。如果0~n都有,那么答案为n+1
此方法,创建了哈希表,空间复杂度达不到要求
2. 原地哈希
由于空间复杂度要求为O(1) ,那么就要想到尽量在原地处理,不另外开辟数组,原地处理中就要想到置换操作。
置换什么呢?数组中,最理想的情况是,nums只包含所有1 ~ n的正整数,比如 [1,2,3,4],此时答案为 4+1 = 5。 其他情况,就像数组[3, -1,1,4,4],让所有想要的1 ~ n的正整数回到他该在的位置就很容易看出其他不符合要求的部分,最简单的方法就是让值1 ~ n去对应数组的索引0~n-1。也就是值为val的元素应该呆在索引val-1上 (val>0 && val<=n) 。
对于-1就没有属于它的位置,4重复了,有一个4该回到的位置被占用了。
代码
func firstMissingPositive(nums []int) int {
n := len(nums)
for i:=0;i<n;i++{
// 用for的原因:
// 希望在i这个位置上,能够将值i+1置换过来。如果用if的话,
// 如果本次没将值i+1置换过来,后续就没机会再来遍历索引i了
// nums[i]!=nums[nums[i]-1]代表两值相等就会进入死循环
for nums[i]>0&&nums[i]<=n&&nums[i]!=nums[nums[i]-1]{
nums[nums[i]-1],nums[i] = nums[i],nums[nums[i]-1]
}
}
for i:=0;i<n;i++{
if nums[i]!=i+1{
return i+1
}
}
return n+1
}
合并区间
题目描述
给你若干个区间的集合,每个区间用两个整型描述,第一个整型是区间的开始元素值,第二个是区间的结束元素值。将可以合并的区间合并,最终输出合并后的所有区间。
\
思路
首先按区间开头元素大小对区间进行排序得到如下的区间集合:
\
维护一对双指针,遍历区间集合。假设目前遍历到区间k,k是一个新合并区间的开始区间,k[0],k[1]分别表示区间的开始和结尾元素。
将left设置为k[0],right设置为k[1],然后进入下一个区间(k+1)。 如果right >= (k+1)[0]那么right设为max((k+1)[1],right)。如果right < (k+1)[0] 则进入下一个合并区间。
代码
func merge(intervals [][]int) [][]int {
sort.Slice(intervals,func (a,b int)bool{
return intervals[a][0]<intervals[b][0]
})
res := make([][]int,0)
n := len(intervals)
// 由于第一个区间一定是第一个合并区间的开始,先初始化left和right
left := intervals[0][0]
right := intervals[0][1]
// 从第二个区间开始遍历
for i:=1;i<n;i++{
if intervals[i][0]<=right{
right = max(intervals[i][1],right)
}else{
// 进入下一个合并区间前保存结果
res = append(res,[]int{left,right})
left = intervals[i][0]
right = intervals[i][1]
}
}
// 保存最后一个合并区间结果
res = append(res,[]int{left,right})
return res
}
func max(a,b int)(max int){
max = a
if b>a{
max = b
}
return
}