LeetCode128 最长连续序列

100 阅读2分钟

leetcode.cn/problems/lo…

image.png

第一思路:排序法(超时)

func longestConsecutive(nums []int) int {
    if len(nums) <= 1{
        return len(nums)
    }
    continueListLenMap := make(map[int]int) // index: 以此为起点的连续子数组长度
    sort.Slice(nums, func(i,j int) bool{
        return nums[i] < nums[j]
    })
    for idx, _ := range nums{
        lens := 1
        for j:=idx+1;j<len(nums);j++{
            if nums[j] - nums[j-1] == 1{
                lens++
            } else if nums[j] == nums[j-1]{
                continue
            } else{
                break
            }
        }
        continueListLenMap[idx] = lens
    }
    res := 0
    for _, v := range continueListLenMap{
        if v > res{
            res = v
        }
    }
    return res
}

解法一:哈希法

对原数组排序之后连续的序列就很容易找到了。不过排序的时间复杂度是 O(NlogN),而题目要求我们时间复杂度为 O(N),这就得另想办法了 想找连续序列,首先要找到这个连续序列的开头元素,然后递增,看看之后有多少个元素还在 nums 中,即可得到最长连续序列的长度了。

我们可以用空间换时间的思路,把数组元素放到哈希集合里面,然后去寻找连续序列的第一个元素

例如nums = [8,4,9,1,3,2],我们先找到 1,然后递增,找到了 2, 3, 4,这就是一个长度为 4 的连续子序列。又继续递增,中间5,6,7没找到,直到找到 8,作为新的连续子序列起点,递增到了 9,这是一个长度为 2 的连续子序列

func longestConsecutive(nums []int) int {
    if len(nums) <= 1{
        return len(nums)
    }
    set := make(map[int]struct{})
    for _, v := range nums{
        set[v] = struct{}{}
    }
    res := 0
    for num := range set{ // 遍历哈希表
        if _, ok := set[num-1]; ok{ // 找的到比num更小的,说明它不是连续子序列的第一个元素
            continue
        }
        // 找到最小的起始元素,开始计算长度
        curNum := num
        curLen := 1
        for{ // 不断寻找下一个数是不是在哈希表中
            if _, ok := set[curNum+1]; ok{
                curLen++
                curNum++
            }else{
                break
            }
        }
        res = max(res, curLen)
    }
    return res
}

func max(a, b int)int{
    if a > b{
        return a
    }
    return b
}
  • 时间复杂度:O(n),其中 n 是 nums 的长度。
    • 在二重循环中,每个元素至多遍历两次:在外层循环中遍历一次,在内层循环中遍历一次。所以二重循环的时间复杂度是 O(n) 的。比如 nums=[1,2,3,4],其中 2,3,4 不会进入内层循环(命中continue逻辑),只有 1 会进入内层循环。所以,一般只有连续子数组的首个数字会被遍历2次
  • 空间复杂度:O(n)