题目描述:
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
今日学习:
1.set()方法不止可以去重,要熟悉has等操作
2.map
感觉map和set的做法类似,但是还是要熟悉每个操作的具体实现方法,可以少走很多弯路。
题解1:我自己想的,时间复杂度其实不满足要求,没想到通过了,但是时间和空间都有很大的优化空间
var longestConsecutive = function(nums) {
if(nums.length == 0) return 0
if(nums.length == 1) return 1
let o = nums.sort((a, b) => a-b)
let order = [...new Set(o)]
let start = order.length - 1
let count = new Array(o.length).fill(0)
for(let i = order.length - 1; i > 0; i--) {
if(order[i] - order[i-1] == 1) {
count[start]++
}else {
start = i - 1
}
}
let res = Math.max(...count) + 1
return res
};
题解2:算是题解1的优化版
var longestConsecutive = (nums) => {
if (nums.length === 0) return 0
nums.sort((a, b) => a - b)
let max = 1
let count = 1
for (let i = 0; i < nums.length - 1; i++) {
let cur = i, next = i + 1
if (nums[cur] === nums[next]) continue // 相同就跳过本次循环
if (nums[cur] + 1 === nums[next]) { // 发现连续项 count++
count++
} else { // 否则,count重置1
count = 1
}
max = Math.max(max, count)
}
return max
}
题解3:巧用Set()
var longestConsecutive = (nums) => {
const set = new Set(nums) // set存放数组的全部数字
let max = 0
for (let i = 0; i < nums.length; i++) {
if (!set.has(nums[i] - 1)) { // nums[i]没有左邻居,是序列的起点
let cur = nums[i]
let count = 1
while (set.has(cur + 1)) { // cur有右邻居cur+1
cur++ // 更新cur
count++
}
max = Math.max(max, count) // cur不再有右邻居,检查count是否最大
}
}
return max
}
题解4:map
var longestConsecutive = (nums) => {
let map = new Map()
let max = 0
for (const num of nums) { // 遍历nums数组
if (!map.has(num)) { // 重复的数字不考察,跳过
let preLen = map.get(num - 1) || 0 // 获取左邻居所在序列的长度
let nextLen = map.get(num + 1) || 0 // 获取右邻居所在序列的长度
let curLen = preLen + 1 + nextLen // 新序列的长度
map.set(num, curLen) // 将自己存入 map
max = Math.max(max, curLen) // 和 max 比较,试图刷新max
map.set(num - preLen, curLen) // 更新新序列的左端数字的value
map.set(num + nextLen, curLen) // 更新新序列的右端数字的value
}
}
return max
}