剑指 Offer 58 - II. 左旋转字符串
剑指 Offer 58 - II. 左旋转字符串

对于此题,如果用允许开辟新空间的算法,那么会比较简单,需要将n个字符移到原字符串的后面,所以考虑新字符串从位置为n处开始添加原字符串中的字符,再从0遍历至n,添加原字符串中的字符。
对于给定的k,因为此题给定了k < s.length。但我们为了追求普适性,可以看出一躺s.length次数得到的新字符串和原字符串相同,所以可以对k取模,即k %= s.length。
点击查看代码
class Solution {
public String reverseLeftWords(String s, int n) {
if(null == s || s.isBlank()) return s;
StringBuilder sb = new StringBuilder();
int l = s.length();
n = n % l;
for(int i = n; i < l; i++) sb.append(s.charAt(i));
for(int i = 0; i < n; i++) sb.append(s.charAt(i));
return sb.toString();
}
}
[0, 1, 2, 3, ..., n - 1, n, n + 1, n + 2,... , s.length - 1]
反转后:
[n, n + 1, n + 2,... , s.length - 1, 0, 1, 2, 3, ..., n - 1,]
然后再考虑如何反转可以在常数空间内由上式得下式。
可发现先对于反转的两个部分,他们的相对次序依旧保持不变,而是两个部分的次序发生了变化,由此推断由多次反转组成。故而先有全局反转后,将[n - s.length-1]与[0, n-1]两个部分的次序调整,再观察发现两个部分依然都是保持着升序,所以需要对每个部分的次序再次反转,最后即可得到结果。
点击查看代码
class Solution {
public String reverseLeftWords(String s, int n) {
if(null == s || s.isBlank()) return s;
int l = s.length();
n = n % l;
char[] str = s.toCharArray();
// 反转[0, s.length - 1]
int start = 0, end = l - 1;
swap(str, start, end);
start = 0; end = l - n - 1;
swap(str, start, end);
start = l - n; end = l - 1;
swap(str, start, end);
return new String(str);
}
private void swap(char[] str, int start, int end) {
while(start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
}

浙公网安备 33010602011771号