目录
1.排序子序列
2.倒置字符串
1.排序子序列
排序子序列_牛客笔试题_牛客网 (nowcoder.com)
首先题干中提到非递增序列和非递减序列,那么我们就要先弄明白什么是上述2种序列:
非递增序列:a[i] >= a[i+1]
如:3 2 1 或者 3 3 2 2 1
非递减序列:a[i] <= a[i+1]
如:1 2 3 或者 1 2 2 3
分析:那么如何划分序列?
可以从我上面例举的非递增或者非递减序列中发现,a[i]和a[i+1]重复完全不影响这个序列是什么序列,所以首先我们可以考虑在出现这种情况的时候直接遍历过去,再看划分子序列的关键点,是在当前这种序列中出现不符合特点的情况(出现另一种序列的特征),那么当前这种序列结束,一定可以划分出子序列。
比如题干:1 2 3 2 2 1
1 2 3是非递减序列,比较过程是:1和2比较,判断出当前是非递减序列,在这个条件下循环依次往后一直比较判断,当比较下图3和2时,此时已经不符合非递减序列的特点,此时可以划分出1个子序列。
小细节:我们使用a[i]和a[i+1]的方式进行遍历序列比较,遍历条件i<n(n为序列长度),当i=n-1时,此时i+1=n,如果只开n个空间的话,此时下标非法,所以我们要多开1个空间,即n+1。数据我们就放0,因为题干数据范围>=1,0比最小的数还小,并不影响划分子序列。
现在来看代码:(有注释很好懂)
#include <iostream>
#include<vector>
using namespace std;
int main() {
int n=0;
cin>>n;
vector<int>v;
v.resize(n+1);//多开一个防止越界
v[n]=0;//数据范围是1<=n<=10^5,0比最小的还小,不影响比较
for(int i=0;i<n;i++)
{
cin>>v[i];
}
//初始化完成
int i=0,count=0;
while(i<n)
{
//非递减序列
if(v[i]<v[i+1])
{
//i<n是为了防止i走到n导致越界
while(i<n&&v[i]<=v[i+1])
{
i++;
}
//退出while那么一定走到了边界
count++;
i++;
}
else if(v[i]==v[i+1])
{
i++;//相同不影响直接跳过
}
//非递增序列
else
{
//i<n是为了防止i走到n导致越界
while(i<n&&v[i]>=v[i+1])
{
i++;
}
//退出while那么一定走到了边界
count++;
i++;
}
}
cout<<count<<endl;
return 0;
}
2.倒置字符串
倒置字符串__牛客网 (nowcoder.com)
这个题相当经典,相信大家应该都做过。
倒置字符串,只需要整体先倒置一遍,再把每个单词倒置一遍就可以达到输出要求。
我们来说说细节,reverse没得说,在algorithm头文件里。读取带空格的字符串使用getline(cin,str_name),str_name是你定义的字符串名称。
我们使用迭代器来寻找要倒置的位置,string的迭代器就是指针(可以看我string类详解中访问及遍历操作中的迭代器模拟实现),迭代器在使用的过程中通常是用!=str_name.end()来实现遍历条件的。
图解:
来看代码:(有注释很好懂)
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
string s;
getline(cin,s);
reverse(s.begin(),s.end());
//直接使用auto让编译器自动识别类型
auto start=s.begin();
while(start!=s.end())
{
auto end=start;
while(end!=s.end()&&*end!=' ')
{
end++;
}
//出来就一定会翻转
reverse(start,end);
//翻转后更新迭代器
//未走到末尾,即走到空格
if(end!=s.end())
{
start=end+1;
}
//走到末尾
else
{
start=end;
}
}
cout<<s<<endl;
return 0;
}