最大连续子序列
2016-07-02 10:37
141 查看
周六早上做了一道A题,按道理讲应该难度不大,但涉及到一个基本的知识点是求最大连续子序列,其实这个东西我不怎么熟悉,在网上看到了别人的相关代码,顺利AC。
codeforces题目链接在这里:http://codeforces.com/contest/688/problem/A
最大连续子序列相关资料却是别人整理的leetcode:http://www.2cto.com/kf/201512/452408.html
codeforces中这个题目本质上就是求最大连续子序列,下面内容是第二个链接中对最大连续子序列这类题目的分析,工具为哈希表。
哈希表插入和查找一个数的时间是O(1),因此可以使用哈希表来保存数组,以保障数组中的元素查找是常量时间;一个数和它相邻的数都在同一个连续子序列中,因此,在某个数开始进行最长连续子序列判断的时候,可以将与它在同一个连续子序列中的元素标记为不作为判断的开始,因为该元素锁在的连续子序列处理过了,从而减少比较次数,降低计算复杂度。
由于C++实现中的哈希表是一个无序字典类型,因此,可以将数组元素作为关键字,每一个元素标记位作为每一个关键字的值。
对于数组中的每一个元素,先判断其所在的连续子序列是否处理过了,如果处理过了,则直接处理下一个元素;如果没处理过,则以其为中心,向左向右查找是否有相邻数存在于数组中,如果存在就将长度加1,并将该元素的标记位置位,表示该元素所在的连续子序列处理过了,一直查找下去,直到相邻的数字不存在数组中为止,记录序列的长度,然后处理下一个元素。按照这个方法,在进行最长连续子序列查找的过程中,每个元素只被访问过一次,因此计算复杂度为O(n)。
在创建哈希表的过程中,计算复杂度也为O(n),因此整个算法的时间复杂度就是O(n)。
最后贴一下这个题目的代码,当然可能存在更简单的解决办法,毕竟这只是一道A题
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
vector<int> v;
int n, d;
string s;
int judge(string s)
{
for (int i = 0; i < s.size(); ++i)
if (s[i] == '0')
return 1;
return 0;
}
int main()
{
cin >> n >> d;
for (int i = 1; i <= d; ++i)
{
cin >> s;
if (judge(s))
v.push_back(i);
}
int sz = v.size(), res = 0;
map<int, bool> HashTable;
//build the hash table
for (int i = 0; i < sz; ++i)
HashTable[v[i]] = false;
//find the longest consecutive sequence
int LongestNum = 0;
for (int i = 0; i < sz; ++i)
{
int tmp = v[i];//先向右查找
if (HashTable[tmp])
continue;
int tmpsequence = 1;
//map对象的find函数返回一个迭代器指向键值为key的元素
//如果没有找到就返回指向map尾部的迭代器
while (HashTable.find(++tmp) != HashTable.end())
{
HashTable[tmp] = true;
tmpsequence++;
}
tmp = v[i];//再向左查找
while (HashTable.find(--tmp) != HashTable.end())
{
HashTable[tmp] = true;
tmpsequence++;
}
LongestNum = max(LongestNum, tmpsequence);
}
cout << LongestNum << endl;
return 0;
}
codeforces题目链接在这里:http://codeforces.com/contest/688/problem/A
最大连续子序列相关资料却是别人整理的leetcode:http://www.2cto.com/kf/201512/452408.html
codeforces中这个题目本质上就是求最大连续子序列,下面内容是第二个链接中对最大连续子序列这类题目的分析,工具为哈希表。
哈希表插入和查找一个数的时间是O(1),因此可以使用哈希表来保存数组,以保障数组中的元素查找是常量时间;一个数和它相邻的数都在同一个连续子序列中,因此,在某个数开始进行最长连续子序列判断的时候,可以将与它在同一个连续子序列中的元素标记为不作为判断的开始,因为该元素锁在的连续子序列处理过了,从而减少比较次数,降低计算复杂度。
由于C++实现中的哈希表是一个无序字典类型,因此,可以将数组元素作为关键字,每一个元素标记位作为每一个关键字的值。
对于数组中的每一个元素,先判断其所在的连续子序列是否处理过了,如果处理过了,则直接处理下一个元素;如果没处理过,则以其为中心,向左向右查找是否有相邻数存在于数组中,如果存在就将长度加1,并将该元素的标记位置位,表示该元素所在的连续子序列处理过了,一直查找下去,直到相邻的数字不存在数组中为止,记录序列的长度,然后处理下一个元素。按照这个方法,在进行最长连续子序列查找的过程中,每个元素只被访问过一次,因此计算复杂度为O(n)。
在创建哈希表的过程中,计算复杂度也为O(n),因此整个算法的时间复杂度就是O(n)。
最后贴一下这个题目的代码,当然可能存在更简单的解决办法,毕竟这只是一道A题
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
vector<int> v;
int n, d;
string s;
int judge(string s)
{
for (int i = 0; i < s.size(); ++i)
if (s[i] == '0')
return 1;
return 0;
}
int main()
{
cin >> n >> d;
for (int i = 1; i <= d; ++i)
{
cin >> s;
if (judge(s))
v.push_back(i);
}
int sz = v.size(), res = 0;
map<int, bool> HashTable;
//build the hash table
for (int i = 0; i < sz; ++i)
HashTable[v[i]] = false;
//find the longest consecutive sequence
int LongestNum = 0;
for (int i = 0; i < sz; ++i)
{
int tmp = v[i];//先向右查找
if (HashTable[tmp])
continue;
int tmpsequence = 1;
//map对象的find函数返回一个迭代器指向键值为key的元素
//如果没有找到就返回指向map尾部的迭代器
while (HashTable.find(++tmp) != HashTable.end())
{
HashTable[tmp] = true;
tmpsequence++;
}
tmp = v[i];//再向左查找
while (HashTable.find(--tmp) != HashTable.end())
{
HashTable[tmp] = true;
tmpsequence++;
}
LongestNum = max(LongestNum, tmpsequence);
}
cout << LongestNum << endl;
return 0;
}
相关文章推荐
- 前端开发者如何与UI设计师沟通
- JavaScript实现简单的拖动效果
- Android之手机通知栏Notification的使用(二)
- 进程通信--命名管道(FIFO)
- python的pandas处理数据第一次
- mysql 命令行常用命令
- Unity中的C#学习(二)
- ubuntu下apt-get指令中autoclean,clean,autoremove,--purgeremove说明
- Android开发环境离线工具包
- 强引用、软引用、弱引用、虚引用
- 保护模式下的应用
- PAT (Advanced Level) 1076. Forwards on Weibo (30)
- 介绍 Spring IoC 容器和 bean
- android pull解析xml
- QT5生成可执行文件总结
- “System.StackOverflowException”类型的未经处理的异常在 mscorlib.dll 中发生
- HeadFirstJava——2_类与对象
- jsp分页页面——数字分页
- PAT (Advanced Level) 1075. PAT Judge (25)
- Spring 单元测试