题目的主要信息:
- 一组输入整数序列和一组规则整数序列,和序列的第一个整数为序列的个数(个数不包含第一个整数)
- 整数范围为,序列个数不限
- 从依次中取出,对进行处理,找到满足条件的: 整数对应的数字需要连续包含对应的数字,按照从小到大的顺序处理,重复元素只处理第一个
- 对于每个如果有满足上述条件的,先输出,没有就不输出,再输出满足条件的的个数,然后输出满足条件的全部索引(从0开始),最后再输出全部的
- 最后需要在输出序列的第一个整数位置记录后续整数序列的个数(不包含“个数”本身)
- 需要处理多组输入的情况
方法一:排序+暴力验证
具体做法:
我们按照题目要求按部就班处理就可以了:
首先根据第一个输入得到序列的长度,然后用vector存储,然后根据输入得到的长度,同样利用vector数组存储。
处理完输入以后先用sort函数对序列排序。
然后遍历序列,遇到与前一个相同的元素,我们跳过,以此来去重。然后遍历序列,检查每一个中是否包含了连续的,如果有我们计数加1,并临时记录符合条件的下标。
如果上面的计数为0,我们不做任何处理。如果不为0,我们将加入待输出数组末尾,再将刚刚的计数加在后面,最后遍历刚刚记录下标的数组,依次将下标及对应的元素加入待输出数组后面。
最后我们统计待输出的数组长度,先在输出数组前输出就行了。
验证的时候,我们首先比较二者大小,然后找到每次要除10的多少次方余数才能和比较,然后我们就连续对除这个值,每次比较余数即可。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool check(int r, int i){//检查数字i包含数字r
if(r > i) //i比r还小,不可能
return false;
int top = 1;
while(r / top != 0) //记录每次要连续除10的多少次方,余数才能和r比较
top *= 10;
if(r == 0)
top = 10;
int k = 0;
while(i * 10 / top != 0){ //连除比较
if((i % top) == r)
return true;
i /= 10;
}
return false;
}
int main(){
int n, m; //记录序列I和序列R的大小
while(cin >> n){
vector<int> I(n);
for(int i = 0; i < n; i++)
cin >> I[i]; //输入n个整数序列I
cin >> m; //整数序列R的长度
vector<int> R(m);
for(int i = 0; i < m; i++) //输入m个整数序列R
cin >> R[i];
sort(R.begin(), R.end()); //排序
vector<int> res;
for(int i = 0; i < m; i++){
if(i != 0 && R[i] == R[i - 1]) //去重
continue;
int count = 0;
vector<int> index; //记录符合条件的下标
for(int j = 0; j < n; j++){
if(check(R[i], I[j])){
count++;
index.push_back(j);
}
}
if(count != 0){ //如果有出现连续的R[i],添加头部的R[i]及后面有多少个数中出现了
res.push_back(R[i]);
res.push_back(count);
for(int j = 0; j < index.size(); j++){
res.push_back(index[j]);
res.push_back(I[index[j]]);
}
}
}
cout << res.size(); //先输出个数
for(int i = 0; i < res.size(); i++) //再逐个输出
cout << " " << res[i];
cout << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为序列的长度,为序列的长度,我们要对于每个会对每个进行验证,验证的复杂度是常数,因为是数字的十进制位数,而我们也不知道和的具体大小,因此排序复杂度,要加在后面
- 空间复杂度:,辅助数组的最大长度为序列长度,res数组及保存序列的数组都属于必要空间,不属于额外空间
方法二:哈希表+字符串
具体做法:
对于方法一的排序+去重,我们可以用有序哈希表map实现,输入的序列直接进入哈希表,会自动排序去重,后续遍历哈希表就可以了。
而数组作为输出很麻烦,验证是否满足条件也很麻烦,我可以将数字转换成字符串,利用字符串的find函数查找是否出现过,然后所有的待输入的信息我们可以添加到字符串末尾,也可以在其前面添加数量信息及数字
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
int main(){
int n, m; //记录序列I和序列R的大小
while(cin >> n){
vector<int> I(n);
for(int i = 0; i < n; i++)
cin >> I[i]; //输入n个整数序列I
cin >> m; //整数序列R的长度
map<int, int> R;
for(int i = 0; i < m; i++){ //哈希表记录序列R,直接去重加排序
int t;
cin >> t;
R[t] = 1;
}
int total = 0;
string res = ""; //以字符串的形式输出
for(auto iter = R.begin(); iter != R.end(); iter++){
int count = 0;
string temp = ""; //记录这一轮的R[i]有多少匹配的
for(int i = 0; i < n; i++){
if(to_string(I[i]).find(to_string(iter->first)) != string::npos){ //找到出现数字
count++; //数量加1
temp += to_string(i) + ' ' + to_string(I[i]) + ' '; //添加索引和该数字
}
}
if(count != 0){ //如果有出现连续的R[i],添加头部的R[i]及后面有多少个数中出现了
res += to_string(iter->first) + ' ' + to_string(count) + ' ' + temp;
total += (2 * count + 2); //补充后面增加了多少数
}
}
res = to_string(total) + ' ' + res; //添加总个数
cout << res << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为序列的长度,为序列的长度,我们要对于每个会对每个进行验证,验证的复杂度是常数,因为是数字的十进制位数,而我们也不知道和的具体大小,因此排序复杂度,要加在后面
- 空间复杂度:,辅助空间为哈希表的长度,res字符串及保存序列的数组都属于必要空间,不属于额外空间