【string题解 C++】翻转字符串II:区间部分翻转 | 验证回文串

翻转字符串II:区间部分翻转

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

难度:简单

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。

如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:

输入:s = "abcdefg", k = 2
输出:"bacdfeg"

示例2:

输入:s = "abcd", k = 2
输出:"bacd"

思路

其实这道题难点在于理解题目到底想干嘛,get到它的意图以后,实现起来就不难了。

而理解题意,最好的办法是画图:

【string题解 C++】翻转字符串II:区间部分翻转 | 验证回文串_第1张图片

画出这几种情况后,我们发现,题意实际为:反转每个 下标从 2k 的倍数开始的,长度为 k 的子串。若该子串长度不足 k,则反转整个子串。(理解题意真的很重要!!)

可以对string实现分组,每k个为一组,然后组与组之间间隔着反转(第一组反转,第二组不反转,第三组反转……)。

实现

class Solution {
public:
    string reverseStr(string s, int k) {
        int num=s.size();
        int i=0;
        int multiple=0;    //left的下标是成倍增长的,所以我们引入multiple
        while(i

更好的解决方式

遍历一遍string,下标为2k倍数的都拿去reverse。注意看这里对于末尾的处理,巧妙地运用了min函数:

class Solution {
public:
    string reverseStr(string s, int k) {
        int num=s.size();
        for(int i=0;i

验证回文串

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

难度:简单

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。

示例 2:

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。

示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。

思路

我们可以实例化出两个string变量:str1、str2。

首先,遍历字符串 ,将其过滤出来的数字字符 正着放进str1。

然后,遍历str1 ,将其反着放进str2。

最后,遍历str1和str2,对比两者。

实现

class Solution {
public:
    bool isPalindrome(string s) {
        if(s==" "){
            return true;
        }
        int num=s.size();
        string str1,str2;
        for(int i=0;i='0'&&s[i]<='9'
            ||s[i]>='A'&&s[i]<='Z'
            ||s[i]>='a'&&s[i]<='z'){
                if(s[i]>='A'&&s[i]<='Z'){   //大写转小写
                    s[i]+='a'-'A';
                }
                str1.push_back(s[i]);   //正着插入str1  
            }
        }
        
        string::reverse_iterator rit=str1.rbegin();  //反着插入str2
        while(rit!=str1.rend()){
            str2.push_back(*rit);
            rit++;
        }
​
        for(int i=0;i

更好的解决方式

同样的思路,怎么实现才能优化上面的代码?

1.用库里的函数!多用才能熟练。目前我们不知道有哪些函数可以为我所用,不要紧,看题解,它用的函数我们没用过,那我就自己再写一遍,把这个函数拿出来多用用。

2.字符串的比较不需要再遍历的。直接用str1==str2。

class Solution {
public:
    bool isPalindrome(string s) {
        string str1;
        for(auto ch:s){
            if(isalnum(ch)){
                if(ch>='A'&&ch<='Z'){
                    ch+='a'-'A';
                }
                str1+=ch;
            }
        }
        string str2(str1.rbegin(),str1.rend());
        return str1==str2;
    }
};

这种写法的时间复杂度为O(n)(n为字符串的长度)。空间复杂度为O(n)。

关于函数isalnum:

用于判断是否是数字or字符串。

只有在函数isdigit()(判断是否为数字的)和isalpha()(判读是否为字母的)都返回true时,isalnum才会返回true。

你可能感兴趣的:(力扣,c++)