代码随想录算法训练营第八天 | 344.反转字符串 541.翻转字符串II 卡码网54.替换数字 151.反转字符串中的单词 卡码网55.右旋转字符串

文章介绍了如何使用双指针技巧解决LeetCode中的四个字符串反转问题,包括逐字符反转、翻转指定区间以及右旋转字符串,强调了空间复杂度的考虑和代码实现
摘要由CSDN通过智能技术生成

Leetcode - 344 反转字符串

这道题比较基础我用的是双指针来做的:

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

Leetcode-541 翻转字符串II

这道题我首先想到的是用快慢指针来做,但是需要控制的量有点多越做头脑越乱,就不太好搞,

这个时候我的主要思路还是每当快指针遍历了2k个字符判断这时fast离末尾的距离并根据对应的情况选择翻转,这样一个一个遍历搞得脑子很晕呼呼的,就去看了看题解,发现是可以直接自增2k的

这样就会好很多,因为这时每遍历一次,i就会自增一个wk的区间,再根据此时的i到末尾的距离来判定反转的情况就会容易很多:

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

卡码网-54  替换数字

这道题我也是先看了一眼题解再开始做的,这道题也是可以用双指针的方法来做的,首先先遍历原数组得出数字的个数,接着为新数组开辟对应的空间,接着将原数组元素移到新数组中并将左指针安插在原数组末尾下标处右指针按插在新数组末尾下标处,接着从左指针开始从后向前遍历,遇到字母就移到最后,遇到数字就将其往后的六个空间填充上number。这里有两个语法问题一是为新数组开辟空间是不可以是直接为新数组的size赋值而是用resize函数:

w.size() = s.size() - count + 6 * count;
w.resize(s.size() - count + 6 * count);

第二处是将原数组元素移动到新数组时我们不能直接覆盖,这样会使得新数组的大小与原数组大小一样:

string w;
w.resize(s.size());  // 将 w 的大小设置为 s 的大小
w = s;
// ...

我们可以利用for循环逐一为其赋值。

#include<bits/stdc++.h>
using namespace std;

int main(){
	string s;
	while(cin >> s){
		// 判断数字个数 
		int count = 0;
		for(int i = 0; i < s.size(); i++){
			if(s[i] >= '0' && s[i] <= '9'){
				count++;
			}
		}
		string w;
		w.resize(s.size() - count + 6 * count);
		for(int i = 0; i < s.size(); i++){
			w[i] += s[i];
		}
		int l = s.size() - 1, r =w.size() - 1;
		while(l >= 0){
			if(w[l] >= 'A' && w[l] <= 'z'){
				swap(w[l], w[r]);
				l--;
				r--;
			}else if(w[l] >= '0' && w[l] <= '9'){
				w[r - 5] = 'n'; // 这里简便写法
				w[r - 4] = 'u';
				w[r - 3] = 'm';
				w[r - 2] = 'b';
				w[r - 1] = 'e';
				w[r] = 'r';
				l--;
				r -= 6;
			}
		} 
		cout << w << endl;
	}
	return 0;
}

Leetcode-151 反转字符串中的单词

这道题的思路是香江字符串内全部单词翻转,然后再将每一个单词翻转,接下来的重点在于处理多余空格的问题,这里的空格有三种形式,第一种是在字符串的最左边,第二种是在字符串的最右边,第三种是在字符串中间,正确顺序应该死先去空格再反转字符串,再反转单词就可以了,这里如果我们采用erase的方法,每次遇到空格就erase一下这样做会使时间复杂度上升到O(n^2),这里我们采用快慢指针的方法,快指针向前遍历遇到需要保留的字符就赋值给慢指针,这里我们考虑不同情况下双指针的操作,第一是遇到字符串前面的空格,这里我们fast判断是否为空格,如果是就一直向前遍历知到出现字母为止,然后判断字符串间的空格,如果fast与fast减一处均为空格就直接跳过该次循环进入下一次循环,,再是处理末尾的空格,这是我们已经处理完该字符串了,slow指针已经指向最后一个字符,在这里我们只需要判断slow-1处的字符是否为空格,如果为空格就将字符串的大小resize-1,若果没有空格就resizeslow的大小。去除空格后,反转字符串可以直接用reverse进行翻转,然后翻转字符串子区间我们可以用for循环遍历子区间并反转。

class Solution {
public:
void reverse(string& s, int start, int end){
    int l = start, r = end;
    while(l < r){
        swap(s[l], s[r]);
        l++;
        r--;
    }
}
    string reverseWords(string s) {
        int fast = 0, slow = 0;
        while(s.size() > 0 && s[fast] == ' '){
            fast++;
        } // 处理字段串前面的空格
        for(; fast <= s.size() - 1; fast++){
            if(fast - 1 >= 0 && s[fast - 1] == s[fast] && s[fast] == ' '){
                continue;
            }else{
                s[slow++] = s[fast];
            }
        }
        if(s[slow - 1] == ' '){
            s.resize(slow - 1);
        }else{
            s.resize(slow);
        }
        reverse(s, 0, s.size() - 1);
        int start = 0;
        for(int i = 0; i < s.size(); i++){
            if(s[i + 1] == ' ' || i + 1 == s.size()){
                reverse(s, start, i);
                start = i + 2;
            }
        }
        return s;
    }
};

期间出了几次错误都在最后的子区间翻转上没有明确左右指针的位置。

卡码网 - 55.右旋转字符串

这道题我第一次看就有点思路感觉比较简单,但是并没有考虑空间复杂度,直接就是先开辟一个比原字符串大n的字符串,然后空出前n个空间,将需要反转的后n个字符赋值给最前面的空间,并resize一下去掉多余的空格。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin >> n;
    string s;
    cin >> s;
    int count = s.size();
    string s2(count + n, ' ');
    for(int i = 0; i < count; i++){
        s2[i + n] = s[i];
    }
    for(int i = n; i > 0; i--){
        swap(s2[s2.size() - i], s2[n - i]);
    }
    s2.resize(count);
    cout << s2;
    return 0;
}

接下来考虑不申请额外空间的方法来解决此题目:我们可以猜用全局反转加局部翻转的方式来解决此题,首先我们先将全部字符串进行翻转,在将字符串分成两部分进行翻转,一部分是后n个字符,一部分是前免的所有字符:

#include<bits/stdc++.h>
using namespace std;

void reverse(string& s, int start, int end){
    int l = start, r = end;
    while(l < r){
        swap(s[l], s[r]);
        l++;
        r--;
    }
}

int main(){
    int n;
    cin >> n;
    string s;
    cin >> s;
    reverse(s, 0, s.size() - 1);
    int start = 0;
    for(int i = 0; i < s.size(); i++){
        if(i == n - 1){
            reverse(s, start, i);
            start = i + 1;
        }
        if(i == s.size() - 1){
            reverse(s, start, i);
        }
    }
    cout << s;
    return 0;
}

今天是周天补一下之前落下的作业。

2024/3/3 - 11. 28 

-------------magixx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值