【剑指offer-44】翻转单词顺序列
- 考点:字符串
- 时间限制:1秒
- 空间限制:32768K
- 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
思路:
算法思想:
先翻转整个句子,然后,依次翻转每个单词。
依据空格来确定单词的起始和终止位置
代码:
public class Solution {
public String ReverseSentence(String str) {
if (str.length() == 0) {
return "";
}
char[] ch = str.toCharArray();
// 先把整个字符串给反转了
reverse(ch, 0, ch.length - 1);
int blank = -1;
for (int i = 0; i <= ch.length; i++) {
if ( i == ch.length || ch[i] == ' ') {
// 判断条件,当走到最后的时候,最后一个单词还没有反转就跳出循环了,所以改成小于等于
// i - 1就是空格前面的哪一个,i就是空格,所以blank+1就是空格后面那一个一个
reverse(ch, blank + 1, i - 1);
blank = i; // 空格
}
}
return new String(ch);
}
public void reverse(char[] ch, int low, int high) {
while (low < high) {
char temp = ch[low];
ch[low] = ch[high];
ch[high] = temp;
low++;
high--;
}
}
}
我的问题:
- 判断条件中数组越界了,我先判断了ch[i]是不是空格,后面才判断是不是到了length,但实际上,这样的话,他就访问到了不该访问到的地方,所以造成数组越界。
- 在这里要注意到,循环的条件是小于等于length,不然的话,还没走到最后一个字符,整个循环就结束了,因此,我们没有把最后一个单词给反转过来。所以在这里要进行判断。
- 要注意保存的blank。blank的初始值为-1,每次反转的位置是blank+1,就是空格后面的那个位置,反转的最后一个位置是i-1,因为i是空格位置。
其他思路1:
使用栈操作更加清晰明了,例如“world! hello”:
首先每个字符串一次进栈:
栈顶
hello
栈底
world!
然后依次出栈:hello world!
import java.util.Stack;
public class Solution {
public String ReverseSentence(String str) {
if (str.length() == 0 || str.trim().length() == 0) {
return str;
}
Stack<String> stack = new Stack();
String s = str.trim();
String[] list = s.split(" ");
for (int i = 0; i < list.length; i++) {
stack.push(list[i]);
}
// 栈顶元素
s = stack.pop();
while (!stack.empty()) {
s += " " + stack.pop();
}
return s;
}
}
这个思路就是通过栈进行反转。
在这里有几点需要注意的:
- 每次入栈是以一个单词为单位,因为可以看到,单个单词的顺序是正确的,只是单词之间的顺序有错。
- trim()函数用于清除前后的空格,这里有个特殊情况是" ",就是为单个空格的字符串,在这个地方,要在一开始判断的时候,如果去除前后空格后,长度仍为0,那么直接返回该字符串。
- 用split分割字符串为数组。
- 记得引入Stack的包。