字符串翻转

字符串翻转

问题描述:把前 m 个字符搬到尾部

暴力翻转

首先先将一个字符移到尾部,然后重复 m 次,时间复杂度 O(mn),空间 O(1)

三次翻转

时间复杂度 O(N) 空间 O(1) 分割成两段分别翻转,然后再整体翻转

void reverse(string &s, int from, int to) {
    while(from < to) swap(s[from++], s[to--]);
}

void ReverseStr(string &s, int m) {
    int n = s.length();
    // m 可能大于 n
    m %= s.length();

    reverse(s, 0, m-1);
    reverse(s, m, n-1);
    reverse(s, 0, n-1);
}

151. Reverse Words in a String 单词原地反转

其实思路和字符串的字符翻转差不多,第一次整个字符串反转,每个词的顺序颠倒,然后再双指针扫描空格反转单个词,最后再反转最后一个词

坑:注意去除前中后空格 时间复杂度:O(N) 空间复杂度:O(1)

void reverseWords(string &s) {
    //trimming spaces at start
    int i=0;
    while(i<s.length() && s[i]==' '){
        s.erase(s.begin()+i);
    }

    //trimming spaces from the end.
    int j=s.length()-1;
    while(j>=0 && s[j]==' '){
        s.erase(s.begin()+j);
        j--;
    }

	// CC: 字符串只含空格
    if (s == "") return;
	// 1. reverse whole str
    reverse(s, 0, s.length()-1);
    
	// 2. reverse word by word (two pointers)
    for(i=j=0;i<s.length()-1;++i) {
        if (s[i] == ' ') {
            reverse(s, j, i-1);
            j = i+1;
			// CC: remove spaces before continue
            while (s[i+1] == ' ') s.erase(s.begin()+i+1);
        }
    }
    reverse(s, j, s.length()-1);
}

void reverse(string &s, int from, int to) {
    while(from < to) swap(s[from++], s[to--]);
}

收获

字符串反转的高效操作,三次反转

796. Rotate String

给定字符串 a, b。问是否能够通过 a 字符串的左移得到 b 字符串

解法一:暴力子串拼接 0ms

b 可以通过 a 在某位置分割调转后得到

bool rotateString(string a, string b) {
    if (a.length() != b.length()) return false;
    if (a == b) return true;

    for(int i=0;i<a.size();++i) {
		// 减少不必要的分割
        if (a[i] != b[0]) continue;
        if (a.substr(i, a.size()-i)
			+a.substr(0, i) == b) return true;
    }

    return false;
}

解法二:找规律 4ms

b 一定会出现在两个 a 合并成的新字符串中

bool rotateString(string A, string B) {
    return A.size() == B.size() && (A + A).find(B) != string::npos;
}

收获

string::npos 其实就是 -1 表示没找到

#双指针 #字符串