[leetcode] Longest Consecutive Sequence
2016-03-13 00:20
429 查看
题目:给定一个无序数组,求最长的连续序列的长度。
例如:给定
要求:算法时间复杂度为O(n).
思路一: 看到题目,最直观的想法就是先排序,然后遍历一遍有序数组使用类似动态规划的思想求解最长连续序列。但又要求时间复杂度为O(n),所以就想到了基数排序。基数排序基本上是线性时间复杂度。int型一般为4个字节,可以将int当做无符号整数从低字节到高字节进行基数排序,则相当于有4个关键字,每个关键字(一个字节)取值范围是0~255。由于最高位是符号位(0表示正,1表示负),故排好之后的序列是:从小到大的正数在前,从小到大的负数在后,将负数部分提到正数部分前面,则变为整体有序。具体代码如下:
思路二:看了题目的标签是并查集(Union Find),就是说要将连续的元素置于同一分组中。当访问到某个元素e时,就去查看e+1和e-1在不在数组中,然后分别顺次向+1和-1的方向查找,直到找不到下一个相邻的元素为止;同时要在查找的过程中标记数组中已经访问过的元素。由于哈希查找的时间约为O(1),故整体时间复杂度约为O(n)。代码如下:
例如:给定
[100,4,200,1,3,2],则最长的连续序列为[1,2,3,4], 返回4即可。
要求:算法时间复杂度为O(n).
思路一: 看到题目,最直观的想法就是先排序,然后遍历一遍有序数组使用类似动态规划的思想求解最长连续序列。但又要求时间复杂度为O(n),所以就想到了基数排序。基数排序基本上是线性时间复杂度。int型一般为4个字节,可以将int当做无符号整数从低字节到高字节进行基数排序,则相当于有4个关键字,每个关键字(一个字节)取值范围是0~255。由于最高位是符号位(0表示正,1表示负),故排好之后的序列是:从小到大的正数在前,从小到大的负数在后,将负数部分提到正数部分前面,则变为整体有序。具体代码如下:
class Solution { public: void BucketSort(vector<int>& nums){ int n = nums.size(); int r = sizeof(int); // 一般为4个字节 vector<int> tmp; int c[256]; for(int i=0; i<r; ++i){ tmp = nums; // 计数排序 memset(c,0,sizeof(c)); for(int j=0; j<n; ++j){ int idx = (tmp[j]>>(i*8)) & (0x000000ff); ++ c[idx]; } c[255] = n - c[255]; for(int i = 254; i>=0; --i){ c[i] = c[i+1] - c[i]; } for(int j=0; j<n; ++j){ int idx = (tmp[j]>>(i*8)) & (0x000000ff); nums[c[idx]++] = tmp[j]; } } tmp = nums; int k = n; for(int i=0; i<n; ++i){ if(tmp[i] < 0){ k = i; break; } } int j = 0; for(int i=k; i<n; ++i){ // 负数部分移至前面 nums[j++] = tmp[i]; } for(int i=0; i<k; ++i){ // 正数部分置于其后 nums[j++] = tmp[i]; } } int longestConsecutive(vector<int>& nums) { int ret = 0; if(nums.empty()) return 0; BucketSort(nums); ret = 1; int tmp = 1; for(int i=1; i<nums.size(); ++i){ if(nums[i] == nums[i-1] + 1){ ++ tmp; ret = max(ret, tmp); }else if(nums[i] == nums[i-1]){ // 注意数组中有相同元素 }else{ tmp = 1; } } return ret; } };
思路二:看了题目的标签是并查集(Union Find),就是说要将连续的元素置于同一分组中。当访问到某个元素e时,就去查看e+1和e-1在不在数组中,然后分别顺次向+1和-1的方向查找,直到找不到下一个相邻的元素为止;同时要在查找的过程中标记数组中已经访问过的元素。由于哈希查找的时间约为O(1),故整体时间复杂度约为O(n)。代码如下:
class Solution { public: // 类似并查集分组:访问到一个元素时,检查其相邻元素在不在 int longestConsecutive(vector<int>& nums) { if(nums.empty()) return 0; unordered_map<int,int> map; for(int i=0; i<nums.size(); ++i){ map[nums[i]] = i+1; } unordered_map<int,int>::iterator it; int ret = 1, count = 0; for(it = map.begin(); it != map.end(); ++ it){ if(it->second == 0) continue; ++ count; map[it->first] = 0; int tmp = it->first; while(map.find(--tmp) != map.end()){ ++ count; map[tmp] = 0; } tmp = it->first; while(map.find(++tmp) != map.end()){ ++ count; map[tmp] = 0; } ret = max(ret, count); count = 0; } return ret; } };
相关文章推荐
- iOS子线程更新UI的两种方法
- 走近AbstractQueuedSynchronizer
- error: The requested URL returned error: 401 Unauthorized while accessing h
- easyUi datagrid数据表
- day10 Request&Response
- ioS学习 UITableViewCell 增加、删除、移动
- Rescue
- 《第一行代码》 随手笔记——第三章 UI开发的点点滴滴
- UITableView介绍 之 复杂cell的高度计算
- 1016-06-首页20-封装工具条---UITableView控件距离顶部的间距问题----cell选中时的背景颜色设置
- jsp request跳转页面和response跳转页面
- 232. Implement Queue using Stacks
- Integer.parseInt(String s) 和 Integer.valueOf(String s) 的区别
- 用UIScrollView,UIPageControl来实现滚动视图。
- iOS完美版的UIScrollView无缝循环:你值得一看
- 从sqlcommandbuilder引出的小想法
- 用UIpickView实现省市的联动
- IOS_压缩图片UIImage
- 用Source Insight追踪Arduino的setup和loop
- 1562 Guess the number