JavaRush /Java Blog /Random-TW /Java 中的反轉字串:學習以不同方式反轉字串

Java 中的反轉字串:學習以不同方式反轉字串

在 Random-TW 群組發布
不懂演算法就可以成為優秀的程式設計師嗎?非常非常有爭議。是的,你可以在我們的外包公司找到工作,因為面試時他們問的問題主要是技術性的。 Java 中的反轉字串:學習以不同方式反轉字串 - 1但如果你的決定充滿了拐杖,你會成為優秀的專家嗎?如果你想跳槽到一家更認真的外企,你會遇到主要針對演算法的面試。無論如何,採用最基本的演算法是值得的,因為演算法是程式設計師的朋友。今天我們將討論其中一個主題並討論反轉字串的方法。這裡一切都很簡單。反轉字串就是使字串向後移動。例如: JavaRush Forever ->reverof hsuRavaJ 那麼,如何在 Java 中反轉字串呢?

1. StringBuilder/StringBuffer

最常見且最簡單的方法是使用StringBuilder/StringBuffer
public static String reverseString(String str) {
  return new StringBuilder(str).reverse().toString();
}
最好的解決方案=最簡單的。當被問及如何在 Java 中反轉字串時,這是應該首先想到的。但我們之前討論過演算法,不是嗎?讓我們來看看非開箱即用的解決方案。

2. 數組解決方案

public static String reverseString(String str) {
  char[] array = str.toCharArray();
  String result = "";
  for (int i = array.length - 1; i >= 0; i--) {
     result = result + array[i];
  }
  return result;
}
我們使用toCharArray方法 將字串轉換為陣列。讓我們從數組的末尾開始運行for循環,將字元加入結果字串。

3.用charAt解決

public static String reverseString(String str) {
  String result = "";
  for (int i = 0; i < str.length(); i++) {
     result = str.charAt(i) + result;
  }
  return result;
}
在這種情況下,我們甚至不必將字串拆分為數組,因為我們使用String類別方法charAt提取每個字元(for 循環又是相反的,這允許我們按順序向後獲取字元)

4. 堆疊解決方案

Stack類別已經很久沒有使用了,它被認為已經過時了,但是,作為參考,查看使用它的解決方案將會很有用:
public static String reverseString(String str) {
  Stack<Character> stack = new Stack<>();
  String result = "";
  for (Character character : str.toCharArray()) {
     stack.add(character);
  }
  while (!stack.isEmpty()) {
     result = result + stack.pop();
  }
  return result;
}
在這裡,我們再次使用toCharArray將字串拆分為數組,並將其全部放入具有泛型類型的Stack。接下來,我們開始從棧頂取出元素。由於堆疊的本質是LIFO結構-後進先出(先進後出),元素將向後取出,結果將儲存在結果

5. 遞迴求解

幾乎所有演算法問題都可以使用遞歸來解決。而在這裡我們也離不開她。或甚至沒有它們。畢竟,今天我們將考慮的不僅僅是解決遞歸的方法,而是幾種。
  • 方法一

    public static String reverseString(String str) {
      String rightStr;
      String leftStr;
      int length = str.length();
    
      if (length <= 1) {
         return str;
      }
    
      leftStr = str.substring(0, length / 2);
      rightStr = str.substring(length / 2, length);
    
      return reverseString(rightStr) + reverseString(leftStr);
    }

    我們使用rightStrleftStr變數將傳入的字串分成兩個相等的部分。接下來,使用此拆分,我們將字串拆分為最小的可分割部分(1 個字元)。之後,遞歸開始崩潰,以相反的順序返回字元(將右側的字元放置在左側;將左側的字元放置在右側)

    我們不能忘記,每次遞歸都是對一個方法的多次調用,因此會消耗相當大的資源。好吧,如果我們談論的是具有無法達到的退出條件的遞歸,那麼這就是通往無限大和 StackOverflowError 的路徑。

  • 方法二

    這裡我們需要在方法中加入一個參數——index。

    當這個方法運行時,它的字串長度被賦予-1:

    String str = "JavaRush forever";
    System.out.println(reverseString(str, str.length()-1));

    以及方法本身:

    public static String reverseString(String str, int index) {
      if(index == 0){
         return str.charAt(0) + "";
      }
    
      char letter = str.charAt(index);
      return letter + reverseString(str, index-1);
    }

    我們的索引充當我們現在將使用哪個行元素的指示器(我們將使用末尾的元素)。

    因此,我們在索引到達第一個元素時設定退出條件。

  • 我們將使用字母索引獲得的值與先前執行該方法的結果相加並傳回結果。

  • 方法三

    public static String reverseString(String str) {
      if (str.length() <= 1) {
         return str;
      }
      return reverseString(str.substring(1)) + str.charAt(0);
    }

    這種方法本質上是最簡單的遞歸方法。我們記得,簡單=最好。

    在每次運行期間,我們指定相同的字串,但沒有第一個元素。當達到退出條件時(當我們還剩下一個字元時),遞歸開始崩潰,並且前一個未使用的字元將被添加到每個後續結果中。

6. 使用異或

XOR是邏輯位元運算。對於兩個變量,當且僅當參數之一為 true 而另一個為 false 時,運算結果為 true。
A
0 0 0
0 1 1
1 0 1
1 1 0
您可以在本文中閱讀有關位元運算的更多資訊。下一個解決方案將依賴以下事實:

(A XOR B) XOR B = A
(A XOR B) XOR A = B
方法會是什麼樣子:
public static String reverseString(String str) {
  char[] arr = str.toCharArray();
  int low = 0;
  int high = arr.length - 1;
  String result = "";
  while (low < high) {
     arr[low] = (char) (arr[low] ^ arr[high]);
     arr[high] = (char) (arr[low] ^ arr[high]);
     arr[low] = (char) (arr[low] ^ arr[high]);
     low++;
     high--;
  }
  for (int i = 0; i < arr.length; i++) {
     result = result + arr[i];
  }
  return result;
}
讓我們弄清楚這裡發生了什麼。我們從傳入的字串建立一個陣列。我們創建兩個變數lowhigh,它們儲存用於遍歷數組的索引。因此,一個將從開始移動到結束 - 我們給它值 0,第二個 - 從結束到開始,我們將其設為arr.length - 1。我們進入一個循環,只要索引high大於low ,該循環就會播放。這就是有趣的事情開始發生的地方——異或的使用。讓我們以xy為例。假設arr[high] = 'x'; 其二進位碼將為 1 1 1 1 0 0 0 此時arr[high] = 'n'; 二進位代碼 - 1 1 0 1 1 1 0 我們將在循環中執行 XOR 運算:
  1. arr[低] = (char) (arr[低] ^ arr[高]);

    
    arr[low] = 1 1 0 1 1 1 0
    arr[high] =1 1 1 1 0 0 0
    arr[low] = 0 0 1 0 1 1 0
  2. arr[高] = (char) (arr[低] ^ arr[高]);

    
    arr[low] =  0 0 1 0 1 1 0
    arr[high] = 1 1 1 1 0 0 0
    arr[high] = 1 1 0 1 1 1 0
  3. arr[低] = (char) (arr[低] ^ arr[高]);

    
    arr[low] =  0 0 1 0 1 1 0
    arr[high] = 1 1 0 1 1 1 0
    arr[low] =  1 1 1 1 0 0 0
結果,透過這些操作,我們交換了兩個陣列單元格的值。 arr[high]是從陣列結尾算起的元素數,而arr[low]是從陣列開頭算起的元素數。因此,我們只需將元素與這些索引交換即可。例如,在句子“JavaRush Forever”中的第一次執行時, Jr將被交換,第二次執行時 - ae等。如果我們有奇數個字符,那麼當我們到達middle,我們將被拋出循環(即不需要更改中間元素)。如果是偶數,我們將在處理完所有元素後被拋出。好吧,之後我們進入常規循環並從數組元素建立一個字串。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION