排序子序列,倒置字符串讲解(图文并茂)

目录

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;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值