[牛客网-Leetcode] #查找 #数组 中等 longest-consecutive-sequence

最长连续序列 longest-consecutive-sequence

题目描述

给定一个无序的整数类型数组,求最长的连续元素序列的长度。
例如:
给出的数组为[100, 4, 200, 1, 3, 2],
最长的连续元素序列为[1, 2, 3, 4]. 返回这个序列的长度:4
你需要给出时间复杂度在O(n)之内的算法

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given[100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is[1, 2, 3, 4]. Return its length:4.

Your algorithm should run in O(n) complexity.

解题思路

时间复杂度为O(N)的思路:散列表

  • 关于set和unordered_set的find函数的时间复杂度:

    • set底层是红黑树实现的,因此它的find函数时间复杂度:O(logn)
    • unordered_set底层是哈希表,因此它的find函数时间复杂度:O(1)
    • algorithm里的find函数是顺序查找,复杂度为O(n)
  • 关于set和unordered_set的erase函数:

    • st.erase(it):it为需要删除元素的迭代器,时间复杂度为O(1),可结合find()函数使用。
      st.erase(st.find(100));//利用find()函数找到100,然后用erase删除
    • st.erase(value):value为需要删除元素的值,时间复杂度为O(logN)
      st.erase(100); //删除值为100的元素
  • 本题思路:
    用散列表,首先将数字都映射到散列表上,然后,对于每个数字,找到后就删除,然后向两边同时搜,只要搜到了就删除,最后求出长度。
    哈希表搜是O(1),因为每个数字只会添加一次,删除一次,所以复杂度是O(n)

  • 注意,牛客网中使用unordered_set时要加上头文件#include <unordered_set>

  • 本题的散列表使用unordered_set而不是unordered_map的原因:
    unordered_set是一个不含重复元素的容器,且本题只需要保留元素本身而不用考虑它的个数。

  • 将vector num中的所有元素初始化为unordered_set st的写法:
    unordered_set<int> st(num.begin(), num.end());

#include <unordered_set>
class Solution {
    
    
public:
    int longestConsecutive(vector<int>& num) {
    
    
        int size = num.size();
        if(size <= 1) return size;
        //初始化hash表
        unordered_set<int> st(num.begin(), num.end());
        int res(0);
        for(auto n : num) {
    
    
            //如果没找到该元素,则直接跳过
            if(st.find(n) == st.end()) continue;
            int left(n), right(n);
            //向左寻找
            while(st.find(left - 1) != st.end()) {
    
    
                st.erase(st.find(-- left));
            }
            //向右寻找
            while(st.find(right + 1) != st.end()) {
    
    
                st.erase(st.find(++ right));
            }
            res = max(res, right - left + 1);
        }
        return res;
        
    }
};

时间复杂度为O(NlogN)的思路:先排序,再遍历判断

  • cnt用于记录遍历过程中每次记录的最长连续序列长度,res用于记录最终结果的最长连续序列长度
  • 如果num[i] == num[i - 1],则跳过,继续判断下一个
  • 如果num[i] == num[i - 1] + 1,则res ++
  • 否则,res = max(res, cnt), 并重新开始计数cnt = 1
class Solution {
    
    
public:
    int longestConsecutive(vector<int>& num) {
    
    
        int size = num.size();
        if(size <= 1) return size;
        sort(num.begin(), num.end());
        int cnt(1), res(1);
        for(int i = 1; i < size; i ++) {
    
    
            if(num[i] == num[i - 1]) {
    
    
                continue;
            } else if(num[i] == num[i - 1] + 1) {
    
    
                cnt ++;
            } else {
    
    
                res = max(res, cnt);
                cnt = 1;
            }
        }
        res = max(res, cnt);
        return res;
        
    }
};

猜你喜欢

转载自blog.csdn.net/cys975900334/article/details/106669226