【代码随想录】算法训练营 第八天 第四章 字符串 Part 1

目录

344. 反转字符串

题目

思路

代码

我的解法

随想录解法

541. 反转字符串 ll

题目

思路

代码

LCR 122. 路径加密

题目

思路

代码

151. 翻转字符串里的单词

题目

代码

LCR 182. 动态口令

题目

思路

代码


344. 反转字符串

题目

思路

我的思路是,用双指针,一个指左,一个指右,循环互换即可。

代码随想录的更简单精妙,直接用一个for循环搞定,里面用swap来互换。

代码

我的解法
class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;
        while (left < right) {
            char tmp = s[left];
            s[left] = s[right];
            s[right] = tmp;
            left++;
            right--;
        }
    }
};
随想录解法
class Solution {
public:
    void reverseString(vector<char>& s) {
        for (int i = 0, j = s.size() - 1; i < j; i++, j-- )
            swap(s[i], s[j]);
    }
};

541. 反转字符串 ll

题目

思路

主要是注意剩下的字符数量,然后这里用了库函数reverse,其实也可以自己实现,和上一题的代码差不多。

代码

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

LCR 122. 路径加密

题目

思路

按照现在leetcode里的题意,只需要把点换成空格,这样数组空间不变,一个for循环过去就行了;

但是原来的题目是把原字符串的空格替换为"%20",这样就需要增加字符数组的空间才能放得下。

我们的做法是,统计原字符串中空格的数量,记做count,接下来用resize函数扩充字符数组的空间;

现在放的下来,就需要我们来放"%20",我们还是使用双指针,右指针起初指向扩充后数组的最后一个位置,左指针指向扩充前数组的最后一个位置,要注意扩充前的数组还在扩充后的数组空间里面;

每次左指针先向左移动,遇到非空的字符就赋值给右指针指向的位置,然后右指针也向左移动一位,如果左指针遇到空字符,此时右指针就向后移三位,依次赋值为"0"、"2"、"%",直到最后左右指针相遇,就停止赋值,跳出循环。

代码

class Solution {
public:
    string pathEncryption(string path) {
        int count = 0;
        int l = path.size() - 1;
        for (int i = 0; i < path.size(); i++) 
            if (path[i] == ' ')
                count++;
        path.resize(path.size() + count * 2);
        int r = path.size() - 1; 
        while (l < r) {
            if (path[l] == ' ') {
                path[r--] = '0';
                path[r--] = '2';
                path[r--] = '%';
                l--;
            }
            else {
                path[r] = path[l];
                l--;
                r--;
            }
        }
        return path;
    }
};

151. 翻转字符串里的单词

题目

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

代码

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;   //整体思想参考https://programmercarl.com/0027.移除元素.html
        for (int i = 0; i < s.size(); ++i) { //
            if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
                if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
                while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
                    s[slow++] = s[i++];
                }
            }
        }
        s.resize(slow); //slow的大小即为去除多余空格后的大小。
    }

    string reverseWords(string s) {
        removeExtraSpaces(s); //去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。
        reverse(s, 0, s.size() - 1);
        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。
        for (int i = 0; i <= s.size(); ++i) {
            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
                reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
                start = i + 1; //更新下一个单词的开始下标start
            }
        }
        return s;
    }
};

LCR 182. 动态口令

题目

某公司门禁密码使用动态口令技术。初始密码为字符串 password,密码更新均遵循以下步骤:

  • 设定一个正整数目标值 target
  • 将 password 前 target 个字符按原顺序移动至字符串末尾

请返回更新后的密码字符串。

思路

先将整体翻转,再分别翻转后面target个和剩下的前面的。

代码

class Solution {
public:
    void reverse(string& s, int l, int r) {
        for (int i = l, j = r; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }
    string dynamicPassword(string password, int target) {
        reverse(password, 0, password.size() - 1);
        reverse(password, 0, password.size() - target - 1);
        reverse(password, password.size() - target, password.size() - 1);
        return password;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值