541. 反轉字符串II
1.這道題剛開始把題意理解錯了,以為對于任意長度的字符串都只反轉[0,k-1]以及[2k,3k-1]區間的值。
2.但實際上是要把一個字符串分成若干長度為2k的小區間,反轉前[0,k-1]的字符串,[k,2k-1]保持不變;
3.如果有一個區間字符串字符個數小于k,則全部反轉。
4.雙指針法實現反轉比用索引更方便
class Solution {public String reverseStr(String s, int k) {StringBuilder res = new StringBuilder(s);for(int i=0;i<=s.length()-1;i+=2*k){//每2k長度的區間操作一次if(s.length() >= i+k) reverse(res,i,i+k-1);//如果s字符串長度大于等于i+k,[i,i+k-1]區間反轉,[i+k,i+2k-1]不變else reverse(res,i,s.length()-1);//如果s字符串長度小于i+k,在[i,s.length()-1]區間上全部反轉}return res.toString();}public StringBuilder reverse(StringBuilder s,int startIndex,int endIndex){//雙指針法實現反轉比用索引更方便int left = startIndex;int right = endIndex;while(left<right){char temp = s.charAt(left);s.setCharAt(left,s.charAt(right));s.setCharAt(right,temp);left++;right--;}return s;}
}
import java.util.*;
class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String target = scanner.nextLine();
System.out.print(method(target));
}
public static String method(String str){
StringBuilder sb = new StringBuilder();
for(int i=0;i<str.length();i++){
if(Character.isDigit(str.charAt(i))) sb.append(“number”);
else sb.append(str.charAt(i));
}
return sb.toString();
}
}
替換數字
這道題是ACM格式的,趁這個機會練習一下。要注意以下幾點:
1.類名必須為Main,同時要有主函數。
2.要有輸入輸出,輸出要打印
3.需要自己導入必要的包
補充知識點:
Character.isDigit()判斷字符是否為數字
import java.util.*;
class Main{public static void main(String[] args){Scanner scanner = new Scanner(System.in);String target = scanner.nextLine();System.out.print(method(target));}public static String method(String str){StringBuilder sb = new StringBuilder();for(int i=0;i<str.length();i++){if(Character.isDigit(str.charAt(i))) sb.append("number");else sb.append(str.charAt(i));}return sb.toString();}
}
151.翻轉字符串里的單詞
方法一:自己想的方法,思路比較簡單,但是調試了好久,貼在這里梳理一下思路。
class Solution {public String reverseWords(String s) {ArrayList<StringBuilder> list = new ArrayList<StringBuilder>();//存儲遍歷出來的一個個的無空格的單詞StringBuilder sb = new StringBuilder(s);//先將String轉為StringBuilder類型,便于操作StringBuilder res = new StringBuilder();//存儲最終返回的結果int i = 0;//初始化指針while(sb.charAt(i) == ' ') i++;//將指針移動到有單詞的位置上while(i < s.length()){//遍歷sStringBuilder sbOne = new StringBuilder();//存儲一個單詞的StringBuilderwhile(s.charAt(i) != ' '){//不是空格的時候sbOne.append(s.charAt(i));//字符持續加入sbOne,直到遇到空格i++;if(i >= s.length()) break;//大于等于s.length(),也結束循環}list.add(sbOne);//此時指針i在空格上或者在最后一個字符的下一位,先保存sbOneif(i >= s.length()) break;//如果在最后一個字符的下一位,直接結束循環while(s.charAt(i) == ' '){//如果是空格就持續向下移動,直到遇到單詞i++;if(i >= s.length()) break;//大于等于s.length(),也結束循環}}//此時list已經按序存儲了所有滿足條件的單詞for(int j=list.size()-1;j >= 1;j--){res.append(list.get(j) + " ");}//除了第一個單詞,其他都是一個單詞一個空格地加入resres.append(list.get(0));//第一個單詞直接加入,沒有空格return res.toString();}
}
方法二:
卡哥的方法,先整體反轉,再去除多余的空格,最后再對每一個單詞反轉。卡哥要求空間復雜度為O(1),那方法一就不符合要求了。
class Solution {public String reverseWords(String s) {int length = s.length();StringBuilder sb = new StringBuilder(s);reverse(sb,0,length-1);removeExtraSpace(sb);reverseOneWord(sb);return sb.toString();}public static void reverse(StringBuilder s,int startIndex,int endIndex){//雙指針法實現反轉int left = startIndex;int right = endIndex;while(left < right){char temp = s.charAt(left);s.setCharAt(left,s.charAt(right));s.setCharAt(right,temp);left++;right--;}}public static void reverseOneWord(StringBuilder s){//單個單詞反轉,對于除最后一個單詞之外的單詞//快指針下一個為空說明此時fast處于單詞尾部,[slow,fast]之間的字符反轉//slow變為fast+2,因為要跳過空格//最后一個單詞直接[slow,s.length()-1]反轉int slow = 0;for(int fast = 0;fast < s.length()-1;fast++){if(s.charAt(fast+1) != ' ') continue;else{reverse(s,slow,fast);slow = fast+2;}}reverse(s,slow,s.length()-1);}public static void removeExtraSpace(StringBuilder s){int slow = 0;boolean need=false;for(int fast = 0; fast < s.length();fast++){if(s.charAt(fast) != ' '){s.setCharAt(slow++,s.charAt(fast));//當快指針遇到了單詞的第一個字母,說明slow指針放置完這個單詞之后還要再放一個' 'need = true;}else if(need){//當遇到了空格(一個單詞遍歷結束)并且need為true,將slow指針指向的位置置為' 's.setCharAt(slow++,' '); need = false;}}//但是如果原始字符串本身以空格結尾,倒數第一個單詞遍歷完之后need還是true的,因此新字符串還會添一個' ',這個時候應該長度置為slow-1if(s.charAt(s.length()-1) == ' ') s.setLength(slow-1);//如果原始字符串本身不以空格結尾,新字符串不會添' ',直接s.setLength(slow);else s.setLength(slow);}
}
方法三:
之前寫的一個方法,用字符數組做的,時間復雜度和空間復雜度都很低。
這里的反轉單個單詞的方法非常棒:
public void keyReverse(char[] chars){//start索引是隨著end索引移動而移動的int start = 0;//這里end <= chars.length,end最大可以到chars.length,對應的是reverse(chars,start,end-1);for(int end = 0;end <= chars.length;end++){if(end == chars.length || chars[end] == ' '){reverse(chars,start,end-1);start = end+1;}}}
class Solution {public String reverseWords(String s) {char[] chars = s.toCharArray();char[] charsNew = trim(chars,chars.length);reverse(charsNew,0,charsNew.length-1);keyReverse(charsNew);return String.valueOf(charsNew);}public void keyReverse(char[] chars){//start索引是隨著end索引移動而移動的int start = 0;//這里end <= chars.length,end最大可以到chars.length,對應的是reverse(chars,start,end-1);for(int end = 0;end <= chars.length;end++){if(end == chars.length || chars[end] == ' '){reverse(chars,start,end-1);start = end+1;}}}//該方法用于反轉指定索引的字符串public void reverse(char[] chars,int start,int end){while(start < end){char temp = chars[start];chars[start] = chars[end];chars[end] = temp;start++;end--;}}public char[] trim(char[] chars,int length){//該方法用于去除字符串兩頭的空格以及單詞之間多余的空格int slow = 0;for(int fast = 0;fast< length;fast++){if(chars[fast] != ' '){//遇到非空說明slow后面要加空格了if(slow != 0) chars[slow++] = ' ';//直到找到下一個單詞首字母(非空)while(fast < chars.length && chars[fast] != ' '){chars[slow++] = chars[fast++];}}}//創建一個用于存儲信數組的newChars,可以將多余部分去除char[] newChars = new char[slow];//chars為復制源,起始索引,目標數組,起始索引,要復制的元素數量System.arraycopy(chars, 0, newChars, 0, slow); return newChars;}
}
卡碼網:55.右旋轉字符串
這道題目很簡單,但是解決了我長久以來關于ACM模式的一個困惑:連續用scanner向系統鍵入兩個量的時候,會報錯。
因為:如下面代碼所示, int num = scanner.nextInt();輸入一個整數之后還要鍵入一個回車,這個回車會被當成緊接著要輸入的scanner.nextLine();導致在執行下面代碼中出錯。因此需要鍵入一個scanner.nextLine();消耗掉回車。
scanner.nextLine(); // 消耗掉nextInt后的換行符
import java.util.*;
class Main{public static void main(String[] args){Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();scanner.nextLine();//消耗掉回車String str = scanner.nextLine();int len = str.length();StringBuilder sb = new StringBuilder();for(int i = len-num;i < len;i++){sb.append(str.charAt(i));}for(int i = 0;i<len-num;i++){sb.append(str.charAt(i));}System.out.print(sb.toString());}
}