C++ day8 反转字符串 反转字符串Ⅱ 替换空格 反转字符串里的单词 左旋转字符串

题目1:344 反转字符串

题目链接:反转字符串

对题目的理解

将给定的字符串反转 空间是O(1)

自己的思考

遍历字符串然后存放到新的数组里,但是不满足空间O(1)

想到反转链表使用双指针的思想,所以使用双指针法反转字符串,字符串也是一种数组,所以元素在内存中是连续分布,定义两个指针i,j,一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

C++ day8 反转字符串 反转字符串Ⅱ 替换空格 反转字符串里的单词 左旋转字符串_第1张图片

使用swap交换两个指针处的值。

class Solution {
public:
    void reverseString(vector& s) {
        for(int i=0, j=s.size()-1;i

swap有两种实现方式

1.数值交换

int tmp = s[i];
s[i] = s[j];
s[j] = tmp;

2.位运算

s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];

题目2:541 反转字符串Ⅱ

题目链接:反转字符串Ⅱ

对题目的理解

i)根据整数k,从字符串开头计数,每次计数到2k,就反转2k中的前k个字符;

ii)剩余字符少于k个,则剩余字符全部反转;

iii)剩余字符大于等于k,小于2k,则只反转前k个字符

自己的思考

首先应用字符串的长度对2k取余, 先处理剩下的字符串,使用for循环+swap函数反转;然后用字符串的长度除以2k,看有多少个2k,然后再对每一个字符串内的数据进行for循环+swap函数,很冗余,不推荐。

使用reverse库函数(左闭右开)

在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。

所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)
class Solution {
public:
    string reverseStr(string s, int k) {
       for(int i=0;i

之所以是i+k<=s.size(),为什么有等号,可以举一个典型的例子:
abc字符串 k=3  当i=0时,i+k=3,而s.size()=3,因此可以取等号

自己编写反转程序reverse函数的代码(左闭右闭)

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)或O(n), 取决于使用的语言中字符串是否可以修改.
class Solution {
public:
    void reverse(string& s, int start, int end){
        for(int i=start,j=end;i

另一种思路解法

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)
class Solution {
public:
    string reverseStr(string s, int k) {
       int n = s.size(),pos = 0;
       while(pos

但是这个程序里面有一个疑问:???就是这段代码为什么会报错???

注意分情况要画{}呀,是因为没有打印{},所以continue会直接拦截住  reverse(s.begin()+i, s.end()),使这一句永远都不会执行。

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

题目3:05替换空格

题目链接:替换空格(链接是力扣的)


对题目的理解

(力扣:将'.'替换为空格)  将空格换成%20  注意%20其实是3个字符:%   2    0

自己的思考

还是遍历的思想,遇到空格,就替换为20%,不行,一个位置只能换一个位置,但是20%有两个位置,无法换

双指针法

首先扩充数组到每个空格替换成"%20"之后的大小。先数有多少个空格,有多少个就在后面补上它的2倍,因为有3个字符嘛,相比原来,多了两个个字符;

然后从后向前替换空格,也就是双指针法,过程如下:

i指向新长度的末尾,j指向旧长度的末尾。

当j指针指向不为空格的元素时,将该元素后移到i指针指向的位置,然后i指针和j指针同时向前移一位再判断j指针指向的位置处是否为空格,若不是空格,则继续讲该元素移到i指针指向的位置,若是j指针指向的位置是空格,则i指针处填冲字符0,然后i指针向前移动一位,填充字符2,i指针再向前移动一位,填充%,然后j指针再移动,继续判断该位置处的字符是否为空格.

C++ day8 反转字符串 反转字符串Ⅱ 替换空格 反转字符串里的单词 左旋转字符串_第2张图片

很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

这样做有许多好处:

  1. 不用申请新数组。
  2. 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

剑指offer题目(20%)

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
class Solution {
public:
    string replaceSpace(string s) {
        int count = 0; // 统计空格的个数
        int sOldSize = s.size();
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == ' ') {
                count++;
            }
        }
        // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
        s.resize(s.size() + count * 2);
        int sNewSize = s.size();
        // 从后先前将空格替换为"%20"
        for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
            if (s[j] != ' ') {
                s[i] = s[j];
            } else {
                s[i] = '0';
                s[i - 1] = '2';
                s[i - 2] = '%';
                i -= 2;
            }
        }
        return s;
    }
};

力扣题目(.换成空格)

//力扣题目代码
class Solution {
public:
    string pathEncryption(string path) {
        int count = 0;//统计.的个数
        int size = path.size();
        for(int i=0;i

题目4:151翻转字符串里的单词

题目链接:翻转字符串里的单词

对题目的理解

反转字符串中单词(没有空格)的顺序,s中使用大于等于1个空格将单词分开,返回的单词顺序颠倒且仅在单词之间用单个空格分隔。

自己的思考

以空格结束作为一个单词的标志,或者是判断一个单词,判断这个单词两端都要空格,采用双指针

双指针法

本题不使用辅助空间,空间复杂度为O(1)

解题思路

i)移除多余空格

ii)将整个字符串反转

iii)将每个单词反转

所以,将这段程序进行拆解,分解成两个任务,去空格和翻转

翻转的程序好写


    void reverse(string& s,int start,int end){
        for(int i=start,j=end;i

难点是去空格的程序,因为是有选择的去空格,该段程序有两个解法

①分类讨论去空格

void removeExtraSpaces(string& s){
        int slow = 0, fast = 0;
        //去掉字符串前面的空格
        while(s.size()>0 && fast0 && s[fast-1]==s[fast] && s[fast]==' '){
                continue;
            }//知道fast的紧挨着的两个元素不是空格时为止
            else{
                s[slow] = s[fast];
                slow++;
            }//slow指向不为空格的元素,即英文字母
            }
        if(slow-1>0 && s[slow-1]==' '){//去掉字符串末尾的空格
            s.resize(slow-1);  //resize操作
        }
        else{
            s.resize(slow);//重新设置字符串的大小
        }
        }

②使用双指针法去除空格(这个对我来讲有点难理解)

 void removeExtraSpaces(string& s){//去除所有空格,并在相邻单词之间添加空格,快慢指针
        int slow = 0;
        for(int fast=0;fast

完整代码(解法1):

  • 时间复杂度: O(n)
  • 空间复杂度: O(1) 或 O(n),取决于语言中字符串是否可变
class Solution {
public:
    void removeExtraSpaces(string& s){
        int slow = 0, fast = 0;
        //去掉字符串前面的空格
        while(s.size()>0 && fast0 && s[fast-1]==s[fast] && s[fast]==' '){
                continue;
            }//知道fast的紧挨着的两个元素不是空格时为止
            else{
                s[slow] = s[fast];
                slow++;
            }//slow指向不为空格的元素,即英文字母
            }
        if(slow-1>0 && s[slow-1]==' '){//去掉字符串末尾的空格
            s.resize(slow-1);  //resize操作
        }
        else{
            s.resize(slow);//重新设置字符串的大小
        }
        }

    void reverse(string& s,int start,int end){
        for(int i=start,j=end;i

完整代码(解法2):

  • 时间复杂度: O(n)
  • 空间复杂度: O(1) 或 O(n),取决于语言中字符串是否可变
class Solution {
public:
    void removeExtraSpaces(string& s){//去除所有空格,并在相邻单词之间添加空格,快慢指针
        int slow = 0;
        for(int fast=0;fast

将代码自己按照逻辑又过了一遍,添加了一些没有的注释。

class Solution {
public:
    //首先去除字符串中所有的空格,定义一个函数
    void removespace(string& s){
        //空格在开头
        int slow = 0, fast = 0;
        while(s.size()>0 && fast0 && s[fast]==s[fast-1] && s[fast]==' '){
                continue;
            }
            else s[slow++] = s[fast];
        }
        //空格在结尾
        if(slow-1>0 && s[slow-1]==' '){
            s.resize(slow-1);//这里为啥要是slow-1呢,因为前一段处理中间的数据时,for循环最后进行了slow++
        }
        else s.resize(slow);
    }
    //接着翻转,定义一个函数
    void reverse(string& s,int start,int end){
        for(int i=start,j=end;i

题目5:58-Ⅱ 左旋转字符串

题目链接:左旋转字符串

对题目的理解

把字符串前面的若干个字符转移到字符串的尾部。

解法

局部反转+整体反转

具体步骤为:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串C++ day8 反转字符串 反转字符串Ⅱ 替换空格 反转字符串里的单词 左旋转字符串_第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;
    }
};

你可能感兴趣的:(c++,算法,开发语言)