题意理解
在字符串中找到长度最大的数字子串,如果有多个数字子串长度相等且最大,则按其在字符串中的顺序一次输出。数字子串指由数字连续构成的子串。
方法一
模拟,双指针。从左到右扫描字符串,并重复一下操作:
1、遇到一个数字字符,位置为i,暂停;
2、从i开始往后扫描,直到遇到非数字字符,位置为j;
3、计算当前发现的数字子串长度,并更新;
4、把j的值赋给i,继续扫描。
模拟过程如下:
具体代码如下:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
string s;
while (cin>>s)
{
int i=0;
int maxm = 0;
//记录最长数字子串的起始位置
vector<int> index;
while (i<s.size())
{
if ('0'<=s[i] && s[i]<='9')
{
int j = i + 1;
//找到一个连续的数字子串
while ('0'<=s[j] && s[j]<='9') j++;
//如果和当前最大长度相等,则记录子串的第一个字符
if ((j-i)==maxm)
{
index.push_back(i);
}
//如果大于当前最大长度,则更新
if ((j-i)>maxm)
{
maxm = j - i;
index.clear();
index.push_back(i);
}
i = j + 1;
}
else i++;
}
for (int h=0;h<index.size();h++)
{
for (int k=0;k<maxm;k++) cout<<s[index[h]+k];
}
cout<<','<<maxm<<endl;
}
return 0;
}
时间复杂度: 。虽然是多重循环,但是字符串中的每个字符至多被扫描一次。 空间复杂度: 。使用了一个index数组记录可能的数字子串的起始位置,最坏情况下需要记录N/2次,例如“a1a1a1a1a1a1”。
方法二
先将所有的非数字的字符替换成某个特定字符,例如‘.’,再使用strtok()方法将其进行分隔,最后挑选出最长的数字子串。
具体代码如下:
#include<iostream>
#include<string>
#include<vector>
#include<string.h>
#include<stdio.h>
#include<cstdlib>
using namespace std;
int main()
{
char s[200];
vector<string> num;
while (cin>>s)
{
//替换
for (int i=0;i<strlen(s);i++)
{
if (s[i]<'0' || '9'<s[i]) s[i] = '.';
}
int maxm = 0;
const char *p = ".";
char *split;
//使用strtok分割字符串
split = strtok(s, p);
while (split)
{
//判断子串的长度
if (strlen(split)==maxm)
num.push_back(string(split));
if (strlen(split)>maxm)
{
maxm = strlen(split);
num.clear();
num.push_back(string(split));
}
split = strtok(NULL, p);
}
for (int i=0;i<num.size();i++)
cout<<num[i];
cout<<','<<maxm<<endl;
}
return 0;
}
时间复杂度: 。在替换字符时遍历了一遍字符串。 空间复杂度: 。使用了一个num数组记录下可能的最长数字子串。