在对字符串进行反转操作时,要使时间复杂度为O(n),那么就需要在本串上操作,也就是双指针法。
模板
使用此模板后,只需要在反转的区间做做文章。
public char[] reverse(char[] array, int left, int right) {
for (; left < right; left++, right--) {
char temp = array[left];
array[left] = array[right];
array[right] = temp;
}
return array;
}
541.反转字符串 II
其实在遍历字符串的过程中,只要让 i += (2 k),i 每次移动 2 k 就可以了,然后判断是否需要有反转的区间。
public String reverseStr(String s, int k) {
char[] array = s.toCharArray();
int i = 0;
for (; i < array.length; i += 2 * k) {
if (i + k <= array.length) {
array = reverse(array, i, i + k - 1);
continue;
}
array = reverse(array, i, array.length - 1);
}
return new String(array);
}
public char[] reverse(char[] array, int left, int right) {
for (; left < right; left++, right--) {
char temp = array[left];
array[left] = array[right];
array[right] = temp;
}
return array;
}
151.翻转字符串里的单词
不要使用辅助空间,空间复杂度要求为O(1)。
不能使用辅助空间之后,那么只能在原字符串上下功夫了。
想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
- 移除多余空格
- 将整个字符串反转
将每个单词反转 ```java class Solution { /**
* 水题做法
*
* @param s
* @return
*/
/* public String reverseWords(String s) {
String[] strings = s.trim().split(" ");
StringBuffer stringBuffer = new StringBuffer();
for (int k = strings.length - 1; k >= 0; k--) {
if (strings[k] != "") {
if (k > 0) {
stringBuffer.append(strings[k]).append(" ");
} else {
stringBuffer.append(strings[k]);
}
}
}
return String.valueOf(stringBuffer);
}
*/
public String reverseWords(String s) {
// 去除首尾空格
StringBuilder sb = removeSpace(s);
// 反转所有字符
reverseString(sb, 0, sb.length() - 1);
// 反转其中单词
reverseEachWord(sb);
return String.valueOf(sb);
}
/**
* 去掉空格
*
* @param s
* @return
*/
private StringBuilder removeSpace(String s) {
StringBuilder sb = new StringBuilder();
int start = 0, end = s.length() - 1;
// 去掉首尾空格
while (s.charAt(start) == ' ') start++;
while (s.charAt(end) == ' ') end--;
while (start <= end) {
// 不存在空格追加进去
char c = s.charAt(start);
if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
start++;
}
return sb;
}
/**
* 反转字符串指定区间[start, end]的字符
*
* @param sb
* @param start
* @param end
*/
public void reverseString(StringBuilder sb, int start, int end) {
for (; start < end; start++, end--) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
}
}
/**
* 反转每个单词
*
* @param sb
*/
private void reverseEachWord(StringBuilder sb) {
int start = 0, end = 1;
int n = sb.length();
while (start < n) {
// 搜索一个单词
while (end < n && sb.charAt(end) != ' ') {
end++;
}
// 反转这个单词
reverseString(sb, start, end - 1);
// 重新开始下一个单词
start = end + 1;
end = start + 1;
}
}
}
<a name="cgPJE"></a>
# 剑指Offer58-II.左旋转字符串
这道题目也非常类似,依然可以通过局部反转+整体反转 达到左旋转的目的。<br />具体步骤为:
1. 反转区间为前n的子串
1. 反转区间为n到末尾的子串
1. 反转整个字符串

```java
class Solution {
public String reverseLeftWords(String s, int n) {
s = reverse(s, 0, n - 1);
s = reverse(s, n, s.length() - 1);
s = reverse(s, 0, s.length() - 1);
return s;
}
public String reverse(String s, int i, int j) {
char[] chars = s.toCharArray();
for (; i < j; i++, j--) {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return String.valueOf(chars);
}
}