2022年10月19日算法学习打卡

98 阅读1分钟

day8

344.反转字符串

建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数

题目链接/文章讲解/视频讲解:programmercarl.com/0344.%E5%8F…

个人思路: 该题特别基础,只需要遍历一次数组,将对应位置(a[0]---a[n])进行交换即可。

代码:

class Solution {
public:
    void reverseString(vector<char>& s) {
        int n = s.size();
        int halfn =n/2;
        int L = 0;
        int R = n-1;
        while(L<R)
        {
            char tmp;
            tmp=s[L];
            s[L]=s[R];
            s[R]=tmp;
            L++;
            R--;
        }
        return ;
    }
};

541. 反转字符串II

建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。

题目链接/文章讲解/视频讲解:programmercarl.com/0541.%E5%8F…

个人思路:

本题采用了一次计数器去统计字符串的个数,其实没有必要,由于在每次处理中都是针对i+2k内的元素进行处理,因此每次将数组的下标移动2k即可(见代码1)。

代码1:

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

代码2:

class Solution {
public:
    string reverseStr(string s, int k) {
        int n =s.size();
        int count =0;
        for(int i =1;i<=n;i++)
        {
            count++;
            if(count==2*k)
            {
                int L = i-2*k;
                int R = i-k-1;
                while(L<R)
                {
                    swap(s[L],s[R]);
                    L++;
                    R--;
                }
                count=0;
            }
        }
        if(count<2*k&&count>=k)
        {
            int L = n - count;
            int R = L + k-1;
             while(L<R)
                {
                    swap(s[L],s[R]);
                    L++;
                    R--;
                }
        }else if(count<k)
        {
            int L = n - count;
            int R = n-1;
             while(L<R)
                {
                    swap(s[L],s[R]);
                    L++;
                    R--;
                }
        }
        return s;
    }
}

剑指Offer 05.替换空格

建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。

题目链接/文章讲解:programmercarl.com/%E5%89%91%E…

个人思路: 本题是剑指Offer里面的第一道编程题,地位不亚于单词书里面的abandon:)。该题的主要思路是首先遍历整个字符串,计算出空格的个数,然后根据空格的个数扩充字符串的大小,然后从后往前遍历,填入对应的字符。

代码:

class Solution {
public:
    string replaceSpace(string s) {
        int n = s.size();
        int conut = 0;
        for(int i =0;i<n;i++)
        {
            if(s[i]==' ') conut++;
        }
        int newsize = n+conut*2;
        s.resize(s.size() + conut * 2);
        int R = newsize-1;
        int L = n-1;
        while(conut&&L<R)
        {
            if(s[L]!=' ') {
                s[R--] =s[L--];
            }else{
                s[R--]='0';
                s[R--]='2';
                s[R--]='%';
                L--;
                conut--;
            }
        }
        return s;
    }
};

151.翻转字符串里的单词

建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。

题目链接/文章讲解/视频讲解:programmercarl.com/0151.%E7%BF…

个人思路: 该题的做法是先将整个字符串进行翻转,然后再单独的将字符提取出来,单独对字符进行翻转。主要的难点在于对空格的处理,采用双指针的办法处理空格,首先是处理前导0,快指针记录第一个不为空格的字符,将其全部移动慢指针对应的位置(慢指针从0开始),处理中间的思路与上述类似,记住处理s[j-1]和s[j]保证处理后有一个空格,处理完所有元素后,将最后的空格进行截断,移动元素的思路类似。

代码:

class Solution {
public:
    // void reverse(string& s, int start, int end){ //翻转,区间写法:左闭又闭 []
    //     for (int i = start, j = end; i < j; i++, j--) {
    //         swap(s[i], s[j]);
    //     }
    // }
    void removespace(string& s){
        int n = s.size();
        int i =0;
        int j =0;
        while(1){     //j对应为字符串s中第一个不为0的下标
            if(s[j]!=' ') break;
            j++;  
        }
        while(j<n){
            if(j-1>0 && s[j]==' '&& s[j-1]==s[j])
            {
                j++;
            }
            else
            {
                s[i++]=s[j++];
            }            
        }
        if(i-1>0&&s[i-1]==' ') s.resize(i-1);
        else s.resize(i);
        return;

    }
    string reverseWords(string s) {
        int n = s.size();
        int L = 0;
        int R = n-1;

        while(L<R){ 
            swap(s[L],s[R]);
            L++;
            R--;
        }
        removespace(s);

        cout<<s;

        
        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
        for (int i = 0; i <= s.size(); ++i) {
            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
                int L = start;
                int R = i-1;
                while(L<R)
                {
                    swap(s[L],s[R]);
                    L++;
                    R--;
                }
                //reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
                start = i + 1; //更新下一个单词的开始下标start
            }
        }
        return s;
    }
};

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

建议:题解中的解法如果没接触过的话,应该会想不到

题目链接/文章讲解:programmercarl.com/%E5%89%91%E…

**个人思路:**具体步骤为:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(),s.begin()+n);
        reverse(s.begin()+n,s.end());
        reverse(s.begin(),s.end());
        return s;
    }
};