不懂算法就可以成为一名优秀的程序员吗?非常非常有争议。是的,你可以在我们的外包公司找到工作,因为面试时他们问的问题主要是技术方面的。 但如果你的决定充满了拐杖,你会成为一名优秀的专家吗?如果你想跳槽到一家更认真的外企,你会遇到主要针对算法的面试。无论如何,采用最基本的算法是值得的,因为算法是程序员的朋友。今天我们将讨论其中一个主题并讨论反转字符串的方法。这里一切都很简单。反转字符串就是使字符串向后移动。例如: 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); }
我们使用rightStr和leftStr变量将传入的字符串分成两个相等的部分。接下来,使用此拆分,我们将字符串拆分为最小的可分割部分(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;
}
让我们弄清楚这里发生了什么。我们从传入的字符串创建一个数组。我们创建两个变量low和high,它们存储用于遍历数组的索引。因此,一个将从开始移动到结束 - 我们给它值 0,第二个 - 从结束到开始,我们将其设置为arr.length - 1。我们进入一个循环,只要索引high大于low ,该循环就会播放。这就是有趣的事情开始发生的地方——异或的使用。让我们以x和y为例。假设arr[high] = 'x'; 其二进制码将为 1 1 1 1 0 0 0 此时arr[high] = 'n'; 二进制代码 - 1 1 0 1 1 1 0 我们将在循环中执行 XOR 运算:
-
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
-
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
-
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
GO TO FULL VERSION