代码随想录算法训练营Day08 | LeetCode344.反转字符串、LeetCode541.反转字符串II、剑指Offer05.替换空格、LeetCode1

139 阅读2分钟

LeetCode344.反转字符串

题目链接:leetcode.cn/problems/re…

思路:双指针法。

C++代码如下:

class Solution 
{
public:
    void reverseString(vector<char>& s) 
    {
        for(int i = 0, j = s.size()-1; i < j; i++,j--)
        {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
        }
    }
};

LeetCode541.反转字符串II

题目链接:leetcode.cn/problems/re…

思路:分为两种情况:1.每隔2k个字符的前k个字符进行反转;剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符;2.剩余字符少于 k 个,则全部反转。按照这两种情况分别处理。

C++代码如下:

class Solution 
{
public:
    string reverseStr(string s, int k) 
    {
        int m = 0, n = 0;
        for(int i = 0; i < s.size(); i += 2*k)
        {
            if(i+k <=s.size())     //1.每隔2k个字符的前k个字符进行反转
            {                      //2.剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
                for(m = i, n = i+k-1; m < n; m++,n--)
                {
                    char tmp = s[m];
                    s[m] = s[n];
                    s[n] = tmp;
                }
            }
            else if(i+k > s.size())   //3.剩余字符少于 k 个,则全部反转。
            {
                for(m = i, n = s.size()-1; m < n; m++,n--)
                {
                    char tmp = s[m];
                    s[m] = s[n];
                    s[n] = tmp;
                }

            }
        }
        return s;
    }
};

剑指Offer05.替换空格

题目链接:leetcode.cn/problems/ti…

思路:数组扩充到每个空格替换成"%20"之后的大小。再使用双指针法从后向前填充元素。

C++代码如下:

class Solution 
{
public:
    string replaceSpace(string s) 
    {
        int count = 0;
        //遍历一遍,看下有几个空格
        for(int i = 0; i< s.size(); i++)
        {
            if(s[i] == ' ')
            {
                count++;
            }
        }
        
        //k个空格,扩展2k长度
        int old_size = s.size();
        s.resize(old_size + 2*count);
        
        //字符向后移动
        int i = 0, j = 0;
        for(i = old_size-1,j = s.size() - 1; i >=0 ;)
        {
            if(s[i] != ' ')
            {
                s[j] = s[i];
                i--;
                j--;
            }
            else
            {
                s[j] = '0';
                s[j-1] = '2';
                s[j-2] = '%';
                j -= 3;
                i--;
            }

        }
        return s;
    }
};

LeetCode151.翻转字符串里的单词

题目链接:leetcode.cn/problems/re…

思路:总体思路是先去除掉原字符串的冗余空格,再把整个字符串翻转过来,然后再把每个单词翻转过来。其中去除冗余空格又分为去除开始的空格,以及中间的重复空格,和去除尾部的空格。总体难度不大。

C++代码如下:

class Solution 
{
public:
        //1.去除冗余空格,去除开始和结尾的空格
        void removeExtraSpaces(string& s)
        {
            int fastIndex = 0;
            int slowIndex = 0;
            int Old_size = s.size();

            //去除开始的空格
            while(s[fastIndex] == ' ')
            {
                fastIndex++;
            }
            //去除中间的重复空格
            for(; fastIndex < Old_size; fastIndex++)
            {
                if((fastIndex-1>0) && (s[fastIndex]==s[fastIndex-1]) && (s[fastIndex] == ' '))  //遇到重复空格
                {
                    continue;
                }
                else
                {
                    s[slowIndex] = s[fastIndex];
                    slowIndex++;
                }
            }
            //去除尾部的空格
            if(slowIndex - 1 > 0 && s[slowIndex - 1] == ' ')
            {
                s.resize(slowIndex - 1);
            }
            else
            {
                s.resize(slowIndex);
            }
        }
        
        //2.整个字符串翻转(2和3步骤顺序调换也可以)
        void reverse(string& s)
        {
            for(int i = 0, j = s.size()-1; i < j; i++, j--)
            {
                swap(s[i],s[j]);
            }
        }
        
        //3.每个单词翻转
        string reverseWords(string s)
        {
            removeExtraSpaces(s);
            reverse(s);

            int p = 0;
            int q = 0;
            int tmp = -1;

            for(int i = 0; i < s.size(); i++)
            {
                if(s[i] == ' ') //遇到空格
                {
                    int m = i-1;  //m为当前单词的最后一位

                    for(p = tmp + 1, q = m; p < q; p++,q--)
                    {
                        int tmp_val = s[p];
                        s[p] = s[q];
                        s[q] = tmp_val;
                    }
                    tmp = i;
                }
                if(i == s.size()-1)
                {
                    for(p = tmp + 1, q = i; p < q; p++,q--)
                    {
                        int tmp_val = s[p];
                        s[p] = s[q];
                        s[q] = tmp_val;
                    }
                }
            }
            return s;
        }   
};

注意的地方:

以下写法,会报错,说是数组越界的意思。因为我还没判断fastIndex-1>0,就直接判断s[fastIndex]==s[fastIndex-1]是否成立,有可能s[fastIndex]==s[fastIndex-1]成立但是它们的前提条件fastIndex-1>0并不成立,所以会数组越界。

if((s[fastIndex]==s[fastIndex-1]) && (fastIndex-1>0) && (s[fastIndex] == ' '))  //遇到重复空格
{
    continue;
}

修改为:先判断fastIndex-1>0再判断s[fastIndex]==s[fastIndex-1]就不会报错了。如下:

if((fastIndex-1>0) && (s[fastIndex]==s[fastIndex-1]) && (s[fastIndex] == ' '))  //遇到重复空格
{
    continue;
}

剑指Offer58-II.左旋转字符串

题目链接:leetcode.cn/problems/zu…

思路:先反转0k-1的字符串,再反转ks.size()-1的字符串,最后反转整个字符串即可。

C++代码如下:

class Solution 
{
public:
    string reverseLeftWords(string s, int n) 
    {
        //1.反转0~k-1的字符串;反转k~s.size()-1的字符串
        for(int i = 0, j = n-1; i<j; i++,j--)
        {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
        }
        for(int i = n,j = s.size()-1; i<j; i++,j--)
        {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
        }

        //2.反转整个字符串
        for(int i = 0,j = s.size()-1; i < j; i++, j--)
        {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
        }
        return s;
    }
};