双指针扫描

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

给定长度为N的字符串S,要构造一个长度为N的字符串T。T初始是空字符串。S由大写字母构成。
构造过程通过反复进行以下任意操作:
从S的头部删除一个字符,添加到T的尾部
从S的尾部删除一个字符,添加到T的尾部
请你构造出字典序尽可能小的字符串T(字典序是指首先比较第一个字符,如果不同则第一个字符
较小的字符串更小,如果相同则比较第二个字符,以此类推)
 

输入描述:

第一行一个整数N,表示字符串的长度(1<=n<=2000)
第二行输入一个长度为N的字符串S

输出描述:

输出构造出的尽可能小的字符串T

示例1

输入

6

ACDBCB

输出

ABCBCD

思路:

主要判断两边相等的情况,每次判断输出左指针还是右指针即可;若两边不同,输出字典序小的;若相同,则继续往中间找(此过程不能移动两边指针的位置),直到遇到不同字符再判断输出哪一个;

代码:

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>

using namespace std;

int main()
{
    int n;
    string s;
    cin >> n >> s;
    int left = 0,right = n - 1;//一个左指针,一个右指针;
    int flag;
    flag = 0;
    int i;
    while(left <= right)
    {
        flag = 0;
        for(i = 0;left + i < right;i ++)
        {
            if(s[left + i] < s[right - i])
            {
                flag = 1;//左边字母小,flag赋1;
                break;
            }
            else if(s[left + i] > s[right - i])
            {
                flag = 0;//右边字母小,flag赋0;
                break;
            }
        }
        if(flag == 1)
        {
            cout << s[left];
            left ++; //++让左指针向右扫描;
        }
        else
        {
            cout << s[right];//--让右指针向左扫描;
            right --;
        }    
    }
    return 0;
}

### 动态数组 动态数组是在程序运行时动态分配内存的数组。在C++里,可借助`new`和`delete`操作符或者`std::vector`容器来实现。使用`new`操作符创建动态数组示例如下: ```cpp int* arr = new int[10]; // 创建一个包含10个整数的动态数组 // 使用数组 delete[] arr; // 释放数组内存 ``` 使用`std::vector`示例: ```cpp #include <vector> std::vector<int> vec(10); // 创建一个包含10个整数的动态数组 ``` ### 键值对 键值对是一种数据结构,将键和值关联起来。在C++中,`std::pair`可表示简单的键值对,`std::map`和`std::unordered_map`能存储多个键值对。`std::pair`示例: ```cpp #include <utility> std::pair<int, std::string> kv(1, "one"); // 创建一个键值对 ``` `std::map`示例: ```cpp #include <map> std::map<int, std::string> myMap; myMap[1] = "one"; ``` ### 键值对数组 键值对数组就是存储多个键值对的数据结构。可以用`std::vector`存储多个`std::pair`或者`std::map`、`std::unordered_map`。示例: ```cpp #include <vector> #include <utility> std::vector<std::pair<int, std::string>> kvArray; kvArray.push_back(std::make_pair(1, "one")); ``` ### set集合 `std::set`是C++标准库中的关联容器,用于存储唯一元素,且元素会自动排序。示例: ```cpp #include <set> std::set<int> mySet; mySet.insert(3); mySet.insert(1); ``` ### auto类型 C++11引入的`auto`关键字可实现类型推导。编译器会依据右值推导出右值的类型,进而确定左边变量的类型。示例: ```cpp auto num = 10; // num的类型会被推导为int auto str = "hello"; // str的类型会被推导为const char* ``` ### 红黑树 红黑树是一种自平衡的二叉搜索树,C++标准库中的`std::map`和`std::set`底层使用红黑树实现。红黑树能保证在最坏情况下基本动态集合操作的时间复杂度为O(log n)。 ### 哈希表 哈希表是根据键(Key)直接访问内存存储位置的数据结构。C++标准库中的`std::unordered_map`和`std::unordered_set`基于哈希表实现。示例: ```cpp #include <unordered_map> std::unordered_map<int, std::string> hashMap; hashMap[1] = "one"; ``` ### <cstdlib>头文件 `<cstdlib>`头文件提供了通用工具函数,如内存分配(`malloc`、`free`)、随机数生成(`rand`、`srand`)、进程控制(`exit`)等。示例: ```cpp #include <cstdlib> int randomNum = rand(); // 生成随机数 ``` ### <ctime>头文件 `<ctime>`头文件提供了处理时间和日期的函数,如获取当前时间(`time`)、格式化时间(`ctime`)等。示例: ```cpp #include <ctime> time_t now = time(0); char* dt = ctime(&now); ``` ### 堆 堆是一种特殊的树状数据结构,分为最大堆和最小堆。在C++中,`std::priority_queue`是基于堆实现的优先队列。示例: ```cpp #include <queue> std::priority_queue<int> maxHeap; maxHeap.push(3); maxHeap.push(1); ``` ### 刷表法 刷表法是动态规划中的一种填表方式,从已知状态出发,更新其他状态的值。通常用于解决具有递推关系的问题。 ### RMQ RMQ(Range Minimum/Maximum Query)即区间最值查询,是指对于长度为n的数列A,回答若干询问RMQ(A, i, j)(i, j ≤ n),返回数列A中下标在i, j里的最小(大)值。可使用线段树、ST表等数据结构实现。 ### 双指针扫描 双指针扫描是一种算法技巧,使用两个指针在数组或链表上移动,用于解决一些搜索、排序等问题。示例: ```cpp #include <vector> std::vector<int> arr = {1, 2, 3, 4}; int left = 0, right = arr.size() - 1; while (left < right) { // 操作 left++; right--; } ``` ### A*搜索 A*搜索是一种启发式搜索算法,常用于路径规划等问题。它结合了Dijkstra算法的最优性和贪心最佳优先搜索的高效性,通过评估函数f(n) = g(n) + h(n)来选择下一个要扩展的节点。 ### 迭代加深搜索 迭代加深搜索是一种深度优先搜索的改进算法,它通过逐渐增加深度限制,避免深度优先搜索陷入无限深度的分支。 ### 随机调整搜索 随机调整搜索是一种基于随机策略的搜索算法,通过随机改变当前解的某些部分,来寻找更优解。 ### 双向广度优先搜索 双向广度优先搜索是从起点和终点同时进行广度优先搜索,当两个搜索方向相遇时,找到最短路径。 ### 启发式搜索算法 启发式搜索算法利用启发函数来引导搜索过程,减少不必要的搜索,提高搜索效率。A*搜索就是一种典型的启发式搜索算法。 ### 最小生成树 最小生成树是一个连通加权无向图中一棵权值最小的生成树。常用算法有Prim算法和Kruskal算法。 ### 各类动态规划 动态规划是一种通过把原问题分解为相对简单的子问题,并保存子问题的解来避免重复计算,从而解决复杂问题的方法。常见的动态规划类型有线性动态规划、区间动态规划、树形动态规划等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

21RGHLY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值