最近做了幾道字符串旋轉的問題,發現其解決思路是一樣的,於是寫此文小結一下。
1、左旋轉字符串
題目描述
字符串的左旋轉操作是把字符串前面的若干個字符轉移到字符串的尾部。請定義一個函數實現字符串左旋轉操作的功能。比如,輸入字符串"abcXYZdef"和數字3,該函數將返回左旋轉兩位得到的結果"XYZdefabc"。
解題思路
這道題當然可以用簡單的substring方法直接得結果,但是這應該不是算法出題者的本意。
解這種題常用的思路是多次翻轉,我們要知道 BA = 旋轉(旋轉(A)旋轉(B))
意思也就是 按題意分割的部分先旋轉,再將整體旋轉,最後就是所得的結果。
若還不懂可以看下圖說明:
明白了實現思路在寫代碼就容易了。
package String;
/**
* @description: 左旋轉字符串
* Input:
* S="abcXYZdef"
* K=3
*
* Output:
* "XYZdefabc"
* @author: Kevin
* @createDate: 2020/2/23
* @version: 1.0
*/
public class LeftRotateString {
public static void main(String[] args) {
String str = "abcXYZdef";
int n = 3;
LeftRotateString solution = new LeftRotateString();
String res = solution.LeftRotateString(str, n);
System.out.println(res); // XYZdefabc
}
public String LeftRotateString(String str, int n) {
if (n >= str.length())
return str;
char[] chars = str.toCharArray();
reverse(chars, 0, n - 1);
reverse(chars, n, chars.length - 1);
reverse(chars, 0, chars.length - 1);
return new String(chars);
}
private void reverse(char[] chars, int i, int j) {
while (i < j)
swap(chars, i++, j--);
}
private void swap(char[] chars, int i, int j) {
char t = chars[i];
chars[i] = chars[j];
chars[j] = t;
}
}
2、右旋轉字符串(沒這道題,自己舉的hh)
要學會舉一反三,有左旋同樣可以實現右旋。
package String;
/**
* @description: 自舉:右旋轉字符串
* * Input:
* * S="abcXYZdef"
* * K=3
* *
* * Output:
* * "defabcXYZ"
* @author: Kevin
* @createDate: 2020/2/23
* @version: 1.0
*/
public class RightRotateString {
public static void main(String[] args) {
String str = "abcXYZdef";
int n = 3;
RightRotateString solution = new RightRotateString();
String res = solution.RightRotateString(str, n);
System.out.println(res); // defabcXYZ
}
public String RightRotateString(String str, int n) {
if (n >= str.length())
return str;
char[] chars = str.toCharArray();
int l = chars.length;
// 區別就是選擇的起始位置
reverse(chars, l - n, l - 1);
reverse(chars, 0, l - n - 1);
reverse(chars, 0, l - 1);
return new String(chars);
}
private void reverse(char[] chars, int i, int j) {
while (i < j)
swap(chars, i++, j--);
}
private void swap(char[] chars, int i, int j) {
char t = chars[i];
chars[i] = chars[j];
chars[j] = t;
}
}
3、翻轉單詞順序列
題目描述
力扣鏈接
輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。爲簡單起見,標點符號和普通字母一樣處理。例如輸入字符串"I am a student. “,則輸出"student. a am I”。
解題思路
同樣是多次旋轉,只不過是分割的條件不在是上題中的n,而是成了判斷單詞。
package String;
/**
* @description: 翻轉單詞順序列
* @author: Kevin
* @createDate: 2020/2/24
* @version: 1.0
*/
public class ReverseSentence {
public static void main(String[] args) {
ReverseSentence solution = new ReverseSentence();
String str = "I am a student.";
System.out.println(solution.ReverseSentence(str)); // student. a am I
}
public String ReverseSentence(String str){
int n = str.length();
char[] chars = str.toCharArray();
int i=0,j=0;
while (j <= n) {
// 空格分割單詞,或者爲最後一個詞
if (chars[j]==' ' || j==n){
reverse(chars, i, j-1);
i = j+1;
}
j++;
}
reverse(chars, 0, n - 1);
return new String(chars);
}
/**
* 翻轉字符串
* @param chars 待翻轉字符串
* @param s 起點
* @param e 終點
*/
private void reverse(char[] chars,int s,int e){
while(s<e){
swap(chars, s++, e--);
}
}
private void swap(char[] chars,int s,int e){
char t = chars[s];
chars[s] = chars[e];
chars[e] = t;
}
}