LeetCode | C++ 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串

52 篇文章 0 订阅

  • 今天的题目主要考虑的是:如果只限定在string上操作,不申请额外的空间,那么只能进行交换,此时就需要用到双指针法,后面就是针对每个问题具体分析。

(1)344.反转字符串

  • 双指针法逐个交换
class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0;
        int right = s.size() - 1;
        while(right > left) {
            char tmp;
            tmp = s[right];
            s[right] = s[left];
            s[left] = tmp;
            right--;
            left++;
        }
    }
};

(2)541. 反转字符串II

  • 该题目重要的是寻找 每 2k 区间的起点,然后进行反转,对于最末尾区间,多一次判断
class Solution {
public:
    string reverseStr(string s, int k) {
        // 该题目重要的是寻找 每 2k 区间的起点,然后进行反转,对于最末尾区间,多一次判断
        for (int i = 0; i < s.size(); i = i + 2 * k) {
            // 每隔 2k 个字符的前 k 个字符进行反转,
            // 或者剩余字符小于 2k 但大于等于 k 个,也进行反转前 k 个
            // 这两种情况 合并为一种
            if (i + k <= s.size()) {
                int left = i;
                int right = i + k - 1;
                while(right > left) {
                    swap(s[left], s[right]);
                    right--;
                    left++;
                }
            } else {
                // 剩余字符少于 k 个,则将剩余字符全部反转。
                int left = i;
                int right = s.size() - 1;
                while(right > left) {
                    swap(s[left], s[right]);
                    right--;
                    left++;
                }
            }
        }
        return s;
    }
};

(3)剑指Offer 05.替换空格

  • 首先需要计算替换空格之后字符串的长度
  • 然后同样利用双指针法进行替换
class Solution {
public:
    string replaceSpace(string s) {
        int count = 0;
        for (char c : s) {
            if (c == ' ') {
                count++;
            }
        }
        int oldSize = s.size() - 1;

        // 需要对原先的字符串进行扩容,因为是一个字符 换成了 3 个
        // 需要统计空格出现的次数
        s.resize(s.size() + count * 2);

        // 同样利用双指针法
        // 从原始字符串最后一个字符开始往后移动;
        int right = s.size() - 1;
        int left = oldSize;
        while (left >= 0) {
            if (s[left] == ' ') {
                s[right] = '0';
                s[--right] = '2';
                s[--right] = '%';
            } else {
                s[right] = s[left];
            }
            left--;
            right--;
        }
        return s;
    }
};

(4)151.翻转字符串里的单词

  • 首先需要对原始字符串移除掉多余的空格
  • 然后将整个字符串进行反转,此时,单词原本的顺序也进行了反转
  • 最后再将每个单词反转过来
class Solution {
public:
    string reverseWords(string s) {
        removeExtraSpace(s);

        int slow = 0;
        int fast = s.size() - 1;
        while (fast > slow) {
            swap(s[fast], s[slow]);
            fast--;
            slow++;
        }

        // 接着对字符串中的每个单词进行反转
        slow = 0;
        fast = 0;
        // 这里为啥 i <= s.size(), 是为了统一, 当i 走到 字符串尾后,就相当于 i 走到字符中的空格处
        for (int i = 0; i <= s.size(); i++) {
            if (s[i] == ' ' || i == s.size()) {
                fast = i - 1;
                while(fast > slow) {
                    swap(s[slow], s[fast]);
                    slow++;
                    fast--;
                }
                slow = i + 1; 
            }
        }
        return s;
    }

    void removeExtraSpace(string &s) {
        // 可以先不考虑空格,在除第一个单词之后的 每次在加单词之前,先加入一个空格
        int slow = 0;
        for (int fast = 0; fast < s.size(); fast++) {
            if (s[fast] == ' ') continue;
            if (slow > 0) {
                s[slow] = ' ';
                slow++;
            }
            while (s[fast] != ' ' && fast < s.size()) {
                s[slow] = s[fast];
                slow++;
                fast++;
            }   
        }
        s.resize(slow);
    }
};

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

  • 正确思路为:局部反转 + 整体反转
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        // 如果只限定在 s 上操作的话,不申请额外的空间,那么只能进行交换
        // 正确思路为:局部反转  +  整体反转
        reverseString(s, 0, n-1);
        reverseString(s, n, s.size() - 1);
        reverseString(s, 0, s.size() - 1);
        return s;
    }

    void reverseString (string &s, int left, int right) {
        while (right > left) {
            swap(s[right], s[left]);
            right--;
            left++;
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值