问题:
将字符串中的单词们首位调换位置。Reverse words in string. Given an input string s, reverse the string word by word.
For example, given s = “the sky is blue”, return “blue is sky the”.
方法一:
public static String reverse(String s) {
String[] tokens = s.split("\\s+");
String result = "";
for (int i = 0; i < tokens.length; i++) {
if (i == tokens.length - 1) {
result += tokens[tokens.length - 1 - i];
} else {
result += tokens[tokens.length - 1 - i] + " ";
}
}
return result;
}
如果不允许使用split()
来parse token的话, 可以尝试two pointer的方式, 一个负责track单词的起始位置, 一个负责track结束位置, 然后跳过空格继续执行。
方法二:
public static String reverse2(String s) {
int start = s.length() - 1;
int end = s.length() - 1;
StringBuilder result = new StringBuilder();
while (start > 0) {
while (start >= 0 && s.charAt(start) != ' ')
start--;
if (result.length() != 0) {
result.append(' ');
} else {
end++;
}
result.append(s.substring(start + 1, end));
end = start--;
}
return result.toString();
}
以上提到的两种方法都是n时间n空间, 也就是我们都创建了一个新的array返回, 也有直接在原数列做交换的方式, 正是上文提到的关于rotate类型的技巧。由于我们观察到:如果给每一个单词都reverse一遍, 最后再整个字符串reverse一遍, 可以得到相同的结果, 比如:
- raw: “ab bc cd”
- target: “cd bc ab”
- reverse each word from raw: “ba cb dc”
- reverse whole string:“cd bc ab”, same as target string.
方法三:
public static String reverse3(String s) {
s = new StringBuffer(s).reverse().toString() + " ";
StringBuilder result = new StringBuilder();
for (int i = 0, j = 0; j < s.length(); j++) {
if (s.charAt(j) == ' ') {
if (j < s.length() - 1) {
result.append(new StringBuffer(s.substring(i, j)).reverse().toString() + " ");
} else {
result.append(new StringBuffer(s.substring(i, j)).reverse().toString());
}
i = j + 1;
}
}
return result.toString();
}
类似的还有刚刚提及的将某数列向某方向rotate的题型,
Rotate an array to the right by k steps in-place without allocating extra space.
For instance, with k = 3, the array [0, 1, 2, 3, 4, 5, 6] is rotated to [4, 5, 6, 0, 1, 2, 3].
其余类型:
public static void rotateRight(int[] numbers, int step) {
rotate(numbers, 0, numbers.length - step);
rotate(numbers, numbers.length - step, numbers.length);
rotate(numbers, 0, numbers.length);
}
public static void rotate(int[] numbers, int start, int end) {
for (int i = 0; i < (end - start) / 2; i++) {
int temp = numbers[start + i];
numbers[start + i] = numbers[end - i - 1];
numbers[end - i - 1] = temp;
}
}