1. 程式人生 > 實用技巧 >[LeetCode] 128. Longest Consecutive Sequence(最長連續序列)

[LeetCode] 128. Longest Consecutive Sequence(最長連續序列)

Description

Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.
給定一個無序整數陣列 nums,尋找其最長連續序列,返回其長度。

Follow up

Could you implement the O(n)

solution?
你能以 \(O(N)\) 時間複雜度解決嗎?

Examples

Example 1

Input: nums = [100,4,200,1,3,2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

Example 2

Input: nums = [0,3,7,2,5,8,4,6,0,1]
Output: 9

Constraints

  • 0 <= nums.length <= 1e4
  • -1e9<= nums[i] <= 1e9

Solution

這題的一個比較暴力的解法就是一個個遍歷。對於每個 num,依次考察 num + 1, num + 2 等是否在陣列內,並更新結果。這種做法時間複雜度為 \(O(N^3)\),通過將陣列轉換成 set,可以降低至 \(O(N^2)\),程式碼如下:

import kotlin.math.max

class Solution {
    fun longestConsecutive(nums: IntArray): Int {
        if (nums.size < 2) {
            return nums.size
        }
        
        val numSet = nums.toSet()
        var result = 1
        for (num in nums) {
            var curResult = 1
            var n = num + 1
            while (n in numSet) {
                n++
                curResult++
            }
            result = max(result, curResult)
        }
        return result
    }
}

\(O(N)\) 的做法在 discussion 裡找到一個。建立一個 map,key 為 num,value 為 num 所在的連續序列的最大長度。對每個不在 map 裡的 num,先檢查 num + 1 和 num - 1 是否在這個 map 裡,更新 num 所在的連續序列的最大長度並儲存。程式碼如下:

import kotlin.math.max

class Solution {
    fun longestConsecutive(nums: IntArray): Int {
        var result = 0
        val map = hashMapOf<Int, Int>()

        for (num in nums) {
            if (!map.containsKey(num)) {
                val left = map[num - 1]?:0
                val right = map[num + 1]?:0

                val sum = left + right + 1
                map[num] = sum

                result = max(result, sum)

                map[num - left] = sum
                map[num + right] = sum
            }
        }
        return result
    }
}