最长连续序列
找出一个数组最长的连续序列(重复的不算),要求复杂度位O(N) 。
示例:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
假如不考虑复杂度,直接哈希搜索,对每个数都找一下它能连续的长度,返回最大的那个长度就行。
class Solution { public: int longestConsecutive(vector<int>& nums) { unordered_map<int,int> hashtb; if(nums.size()<2) return nums.size(); for(int i=0;i<nums.size();i++) { if(hashtb.find(nums[i])!=hashtb.end()) continue; else hashtb.emplace(nums[i],1); } if(hashtb.size()<2) return hashtb.size(); int length=1; int max=1; unordered_map<int,int>::iterator it; unordered_map<int,int>::iterator it1; unordered_map<int,int>::iterator it2; for(it=hashtb.begin();it!=hashtb.end();it++) { it1=it; while(hashtb.find(it1->first+1)!=hashtb.end()) { it2=hashtb.find(it1->first+1); it1=it2; length++; } max=max>length?max:length; length=1; } return max; } };
显而易见的超时,因为时间复杂度是O(N2)。
当然只是练习下哈希表,直接sort排序不比这快?问题是sort复杂度是O(Nlogn),也不满足条件啊。
所以怎么达到O(N)的复杂度?就是每个数只遍历一遍就找出最长的连续数列。
那就加个判定条件,让遍历过的数不再重复遍历。
具体怎么加呢?因为我们必定从哈希表的开头开始遍历,假设为x,找x的前驱x-1,一直找到最小的那个,之后在找他的后驱x+1,一直找到最大的那个,每找到一个就在哈希表里删除这个数,长度+1,最后删除x本身。
继续从开头遍历,直到哈希表删光。
两种erase删除的方式都会超时... 看来利用erase是不行了,毕竟erase()函数本身就有O(N)的时间复杂度
不过有了另一种思路,
上面我们用的是数组的begin()作为基准数,找他的左右连续数,形成一个有序数列。
假如直接找一个有序数列的第一位呢?对于{2,3,5,1,4,7,6,10,11}直接找1,然后形成一个{1,2,3,4,5,6,7}这样的数列,长度为7;之后找到10,形成{10,11}这样的数列,长度为2。
代码如下:
class Solution { public: int longestConsecutive(vector<int>& nums) { if(nums.size()<2) return nums.size(); unordered_map<int,int> hashtb; for(int i=0;i<nums.size();i++) { hashtb.emplace(nums[i],1); } if(hashtb.size()<2) return hashtb.size(); int max=1; int length=1; for(auto it=hashtb.begin();it!=hashtb.end();it++) { if(hashtb.find(it->first-1)!=hashtb.end()) continue;//判断是不是序列起点 不是就下一次循环 else { auto itend=it; while(hashtb.find(itend->first+1)!=hashtb.end())//找到序列的终点和长度 { length++; itend=hashtb.find(itend->first+1); } max=max>length?max:length; length=1; } } return max; } };
好像时间没超过,似乎可行。但时间似乎还是有点长?
PS:为什么定义了<int,int>类型的哈希表? 因为之前想着如果重复的数也算长度的话,在构建哈希表的时候,value就会存储key出现的次数,这样的话,总长度只要加上value就可以了。
还有啥办法呢??我记得unordered_map是无序的,而map和set是有序的。那么我用map或者set找到一个最长的连续序列不也是可以吗?试一下。
class Solution { public: int longestConsecutive(vector<int>& nums) { if(nums.size()<1) return nums.size(); set<int> set; for(int i=0;i<nums.size();i++) { set.insert(nums[i]); } int max=1; int length=1; auto it=set.begin(); while(it!=set.end()) { if(set.count(*it+1)) { while(set.count(*it+1)) { length++; it++; } } else {it++;} max=max>length?max:length; length=1; } return max; } };
好像时间占用和空间占用更大了????时间复杂度O(nlogn)也不满足题意.......
话说那些更快的算法怎么就直接sort了??不过动态规划是好像有点厉害。
posted on 2023-06-18 02:18 WhatAnyWay 阅读(95) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理