leetcode128. Longest Consecutive Sequence 最长连续序列 并查集

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liyunlong41/article/details/85636496

题目地址:https://leetcode.com/problems/longest-consecutive-sequence/

方法1:并查集

这个题的难点在于当更新了某个val后,不能及时更新val周围连续的数值,如val+1, val+2, val-1, val-2等。这里采用并查集的思想,将每一段连续的数值,看做是一个集合,每个集合中有一个leader或者parent。当val值有更新时,判断两边是否有集合,如果有集合那么将这个val合并到集合中,并更新集合中leader的值,如果两边都有集合,那么需要合并两个集合。

ps:并查集的复杂度接近O(1),所以总体复杂度是O(n)  leetcode耗时12ms

func longestConsecutive(nums []int) int {
    n := len(nums)
    if n == 0 {
        return 0
    }
    pre := make(map[int]int)
    count := make(map[int]int)
    for _, val := range nums {
        pre[val] = -100000
    }
    max := 0
    for _, val := range nums {
        if count[val] > 0 {
            continue
        }
        nowVal := 1
        var leftLeader, rightLeader int
        if count[val - 1] > 0 {
            leftLeader = find(val - 1, pre) //左边集合的leader
            nowVal += count[leftLeader]
        }
        if count[val + 1] > 0 {
            rightLeader = find(val + 1, pre)
            nowVal += count[rightLeader]
        }
        // fmt.Println("l:", leftLeader, "r:", rightLeader)
        count[val] = nowVal
        if count[val - 1] > 0 {
            pre[leftLeader] = val
        }
        if count[val + 1] > 0 {
            pre[val] = rightLeader  //集合合并
            count[rightLeader] = count[val]
        }
        if max < count[val] {
            max = count[val]
        }
    }
    return max
}

func find(val int, pre map[int]int) int {
    if pre[val] == -100000 {
        return val
    }
    ret := find(pre[val], pre)
    pre[val] = ret //更新pre数组指向集合leader
    return ret
}

方法2:参考了别人的解法,很巧妙。利用一个map,将所有的数值添加到map中,再次遍历原先数组,先判断当前的值val前面的数val-1是否存在,存在则continue,这是为了保证当前的val是连续序列的最小值。当val是某一段连续序列的最小值时,我们在map中一直找val+1, val+2, val+3...直到找不到,记录这段连续的最长序列,更新答案,另外需要将找到的值在map中删除。

由于每次都是从某段序列的最小值开始找,找不到就退出,找到的就删除,所以最大的复杂度是map的大小。即O(n) 耗时8ms

func longestConsecutive(nums []int) int {
    count := make(map[int]int)
    for _, val := range nums {
        count[val] = 1
    }
    max := 0
    for _, val := range nums {
        if _, found := count[val - 1]; found {
            continue
        }
        tmp := 1
        tmp2 := val + 1
        for {
            if _, found := count[tmp2]; !found {
                break
            }
            delete(count, tmp2)//这里需要删除,防止1,2,3...100000,1,1,1,1,1....
            tmp++
            tmp2++
            
        }
        if max < tmp {
            max = tmp
        }
    }
    return max
}

猜你喜欢

转载自blog.csdn.net/liyunlong41/article/details/85636496