本篇為LeetCode上演算法的簡單問題,Reverse Words in a String III,字串反轉III。
題目如下:
Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order.
Example 1:
Input: "Let's take LeetCode contest" Output: "s'teL ekat edoCteeL tsetnoc"
Note:In the string, each word is separated by single space and there will not be any extra space in the string.
這題字串反轉是要將一段句子中的每個單字前後反轉就好,而不是將整段句子反轉。例如輸入"Let's take LeetCode contest",則輸出應為"s'teL ekat edoCteeL tsetnoc"。
此題一開始想到的解法就是用String.split()
去分割句子中的每個單字為字串陣列,再將字串陣列中的每個單字反轉後重組。
public static String reverseWords(String s) {
String[] ss = s.split("\\s");
StringBuilder sb = new StringBuilder();
for(int i = 0; i < ss.length; i++) {
char[] cc = ss[i].toCharArray();
int lastIndex = cc.length - 1;
for(int j = 0; j < cc.length/2; j++ ) {
cc[j] ^= cc[lastIndex - j];
cc[lastIndex - j] ^= cc[j];
cc[j] ^= cc[lastIndex - j];
}
sb.append(" ").append(cc);
}
return sb.substring(1);
}
但這樣的解法效能不好,因為在String.split()
中會跑迴圈,又加上外面用來返轉單字的迴圈,時間複雜度大於O(N)。
第二個解法是先用StringBuilder.reverse()
先將整段句子反轉後再以String.split()
進行分割並以對的順序重組。
public static String reverseWords(String s) {
StringBuilder sb = new StringBuilder();
String[] ss = sb.append(s).reverse().toString().split("\\s");
int lastIndex = ss.length - 1;
sb = new StringBuilder();
for(int i = lastIndex; i >= 0; i--) {
sb.append(" ").append(ss[i]);
}
return sb.substring(1);
}
雖然比第一次的解法快了一些,但仍只有36%的勝率。
第三個解法是參考多數人的寫法,從句子頭開始每個字元判斷,若該字元為空白,則將空白前的單字進行反轉,例用兩個變數來暫存每個單字的開頭和結束的索引位置,而句字的最後一個字要做額外的判斷。
public static String reverseWords(String s) {
char[] cc = s.toCharArray();
for(int end = 0, start = 0; end < cc.length; end++ ) {
if(cc[end] == ' ') {
reverseWord(start, end - 1, cc);
start = end + 1;
}
if(end == cc.length - 1) {
reverseWord(start, end, cc);
}
}
return String.valueOf(cc);
}
public static void reverseWord(int start, int end, char[] cc) {
while(start < end) {
char temp = cc[start];
cc[start] = cc[end];
cc[end] = temp;
start++;
end--;
}
}
此方法的beats率為65%。
下面的解法是例用StringBuilder.insert(int offset, char c)
將每個字元插最前頭直到碰到空白,但效果也是不好。
public static String reverseWords(String s) {
char[] cc = s.toCharArray();
StringBuilder msb = new StringBuilder();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < cc.length; i++) {
if (cc[i] == ' ') {
msb.append(sb).append(" ");
sb = new StringBuilder();
i++;
}
sb.insert(0, cc[i]);
if (i == cc.length - 1) {
msb.append(sb.toString());
}
}
return msb.toString();
}
參考:
沒有留言:
張貼留言