代码随想录算法训练营第八天| 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串

Leetcode 344.反转字符串
思路分析:
反转字符串直观思路是对称交换两端的字符,即双指针法。

代码实现:

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

Leetcode 541. 反转字符串II
思路分析:
题意说了三种情况,可以拆解为反转前面第k个元素,和少于k的所有元素全部反转。可用for循环,2*k的间隔更新一次,如果i+k小于s.size(),则反转i到i+k区间的元素,可使用std::reverse库函数。如果i+k超过了s.size(),则反转i到末尾的所有元素。因为是对s本身的修改,所以操作完后,直接返回s就好。

代码实现:

class Solution {
public:
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += (2 * k)) {
            if (i + k <= s.size()) {
                reverse(s.begin() + i, s.begin() + i + k );
            } else {
                reverse(s.begin() + i, s.end());
            }
        }
        return s;
    }
};

Leetcode 剑指Offer 05.替换空格
思路分析:
直观解法如方法1,直接申请个辅助空间,遍历原字符串,遇到空格,就替换成"%20"。但该方法空间复杂度不如方法2.
方法2使用双指针从后往前遍历,一个指针指向新字符串的末尾,另一个指向旧字符串的末尾。【《代码随想录》的解法】,该方法时间复杂度为o(n), 空间复杂度为O(1)。
代码实现:
方法1:申请辅助空间

class Solution {
public:
    string replaceSpace(string s) {
    if (s.empty()) {
        return "";
    }
    string s_copy;
    int space_num = 0;
    int origin_length = 0;
    for (auto ch:s) {
        if (ch == ' ') {
            space_num++;
            s_copy.push_back('%');
            s_copy.push_back('2');
            s_copy.push_back('0');
        } else {
            s_copy.push_back(ch);
        }
        origin_length++;
    }

    return s_copy;
    }
};

方法2:不申请辅助空间,双指针法,从后向前操作

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;
    }
};

Leetcode 151.翻转字符串里的单词
思路分析:
本题的思路是先移除前导空格、尾随空格或者单词间多出的空格,再对整个字符串进行反转,最后把每个单词反转,即得到最终结果。reverse的逻辑和反转字符串,反转字符串II一样。本题难点是使用时间复杂度为o(n),空间复杂度为o(1)的算法实现移除多余的空格。
当然有些语言有split和join库函数,如python实现非常简洁,只是失去本题考察的意义。

代码实现:

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 removeExtraSpaces(string& s) {
        int slow = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] != ' ') {
                if (slow != 0) s[slow++] = ' ';
                while (i < s.size() && s[i] != ' ') {
                    s[slow++] = s[i++];
                }
            }
        }
        s.resize(slow);
    }

    string reverseWords(string s) {
        removeExtraSpaces(s);
        reverse(s, 0, s.size() - 1);
        int start = 0;
        for (int i = 0; i <= s.size(); ++i) {
            if (i == s.size() || s[i] == ' ') {
                reverse(s, start, i - 1);
                start = i + 1;
            }
        }
        return s;
    }
};

使用spilt和join:

class Solution:
    def reverseWords(self, s: str) -> str:
        return " ".join(reversed(s.split()))

Leetcode 剑指Offer58-II.左旋转字符串
思路分析:
直观的思路是分别保存n前后的子字符串,然后把前面子字符串的字符放到后面子字符串后面。见方法1。
不用申请额外的内存空间的方法的解题步骤:
1.反转区间为前n的子串;2.反转区间为n到末尾的子串;3.反转整个字符串
代码实现:
方法1:申请额外的内存空间

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        if (s.empty()) {
            return "";
        }
        if (n < 0 || n >= s.length()) {
            return s;
        }
        string array_front;
        string array_rear;
        int i = 0;
        for (auto ch:s) {
            if (i < n) {
                array_front.push_back(ch);
            } else {
                array_rear.push_back(ch);
            }
            i++;
        }
        for (auto ch:array_front) {
            array_rear.push_back(ch);
        }
        return array_rear;
    }
};

方法2:不申请额外的内存空间

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值