在Java中反转String的最有效算法是什么?

时间:2010-03-13 16:56:56

标签: java algorithm string performance

在Java中反转字符串的最有效方法是什么?我应该使用某种xor运算符吗?简单的方法是将所有字符放在堆栈中并将它们重新放回字符串中,但我怀疑这是一种非常有效的方法。

请不要告诉我在Java中使用一些内置函数。我有兴趣学习如何不使用有效的功能,但不知道为什么它有效或如何建立。

21 个答案:

答案 0 :(得分:49)

你说你想知道最有效的方式,你不想知道一些标准的内置方式。然后我告诉你:RTSL(读源,卢克):

查看AbstractStringBuilder#reverse的源代码,它由StringBuilder#reverse调用。我打赌它会做一些你不会考虑进行强大的反向操作的东西。

答案 1 :(得分:36)

以下内容并未涉及UTF-16代理对。

public static String reverse(String orig)
{
    char[] s = orig.toCharArray();
    int n = s.length;
    int halfLength = n / 2;
    for (int i=0; i<halfLength; i++)
    {
        char temp = s[i];
        s[i] = s[n-1-i];
        s[n-1-i] = temp;
    }
    return new String(s);
}

答案 2 :(得分:20)

你说你不想这么简单,但谷歌搜索你应该使用StringBuilder.reverse

String reversed = new StringBuilder(s).reverse().toString();

如果您需要自己实现它,那么以相反的顺序迭代字符并将它们附加到StringBuilder。如果有(或可以)代理对,你必须要小心,因为这些不应该被颠倒。上面显示的方法会自动为您执行此操作,这就是您应该尽可能使用它的原因。

答案 3 :(得分:8)

旧帖子&amp;问题,但仍然没有看到有关递归的答案。递归方法反转给定的字符串s,而不中继内置的jdk函数

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

`

答案 4 :(得分:5)

最快的方法是在reverse()StringBuilder类上使用StringBuffer方法:)

如果你想自己实现它,你可以得到字符数组,分配第二个字符数组并移动字符,在伪代码中这就像:

String reverse(String str) {
    char[] c = str.getCharArray
    char[] r = new char[c.length];
    int    end = c.length - 1

    for (int n = 0; n <= end; n++) {
        r[n] = c[end - n];
    }

    return new String(r);
}

你也可以运行一半的数组长度并交换字符,这些检查可能会减慢速度。

答案 5 :(得分:3)

当您说需要高效算法时,我不确定您的意思。

我能想到的扭转字符串的方法是(在其他答案中已经提到过):

  1. 使用堆栈(您的想法)。

  2. 通过从原始字符串到空字符串/ StringBuilder / char []的相反顺序逐个添加字符来创建新的反向字符串。

  3. 将字符串前半部分中的所有字符与其后半部分中的相应位置进行交换(即第i个字符与第(length-i-1)个字符交换)。

  4. 问题是所有这些都具有相同的运行时复杂度:O(N)。因此,对于非常大的N值(即非常大的弦),任何人都没有明显优于其他人。

    第三种方法确实有一件事要做,另外两种方法需要额外的O(N)空间(对于堆栈或新的String),而它可以在适当的位置执行交换。但是字符串在Java中是不可变的,所以你需要在新创建的StringBuilder / char []上执行交换,因此最终需要额外的O(N)空间。

答案 6 :(得分:3)

public class ReverseInPlace {

  static char[]  str=null;

    public static void main(String s[]) {
      if(s.length==0)
        System.exit(-1);

       str=s[0].toCharArray();

       int begin=0;
       int end=str.length-1;

       System.out.print("Original string=");
       for(int i=0; i<str.length; i++){
         System.out.print(str[i]);
       }

       while(begin<end){
          str[begin]= (char) (str[begin]^str[end]);
          str[end]= (char)   (str[begin]^str[end]);
          str[begin]= (char) (str[end]^str[begin]);

          begin++;
          end--;       
       }

       System.out.print("\n" + "Reversed string=");
       for(int i=0; i<str.length; i++){
         System.out.print(str[i]);
       }

    }
}

答案 7 :(得分:2)

Tomcat.addServlet(context, "yourServletName", resourceConfig());
context.addServletMapping("/yourApi/*", "yourServletName");



 private ServletContainer resourceConfig() {
        return new ServletContainer(new ResourceConfig(
                new ResourceLoader().getClasses()));
    }

答案 8 :(得分:2)

我认为,如果您真的没有性能问题,那么您应该选择最易读的解决方案:

StringUtils.reverse("Hello World");

答案 9 :(得分:1)

如果您不想使用任何内置函数,则需要将字符串返回到其组成部分:字符数组。

现在问题变成了反转数组的最有效方法是什么?在实践中这个问题的答案也取决于内存使用(对于非常大的字符串),但理论上在这些情况下的效率是在数组访问中测量的。

最简单的方法是创建一个新数组,并在反向迭代原始数组并返回新数组时使用您遇到的值填充它。 (虽然使用临时变量,你也可以在没有额外数组的情况下执行此操作,如Simon Nickersons的回答)。

这样,对于具有n个元素的数组,您只能访问每个元素一次。从而给出O(n)的效率。

答案 10 :(得分:1)

我会这样做而不使用任何单个util函数。只需String类就足够了。

public class MyStringUtil {

    public static void main(String[] args) {
        String reversedString = reverse("StringToReverse");
        System.out.println("Reversed String : " + reversedString);
    }

    /**
     * Reverses the given string and returns reversed string
     * 
     * @param s Input String
     * @returns reversed string
     */
    private static String reverse(String s) {
        char[] charArray = s.toCharArray(); // Returns the String's internal character array copy
        int j = charArray.length - 1;
        for (int i = 0; charArray.length > 0 && i < j; i++, j--) {
            char ch = charArray[i];
            charArray[i] = charArray[j];
            charArray[j] = ch;
        }
        return charArray.toString();
    }
}

检查一下。干杯!!

答案 11 :(得分:0)

static String ReverseString(String input) {
    var len = input.Length - 1;
    int i = 0;
    char[] revString = new char[len+1];
    while (len >= 0) {
        revString[i] = input[len];
        len--; 
        i++;
    }
    return new string(revString);   
}

为什么我们不能坚持最简单的循环并喜欢阅读字符并继续添加到char数组,我遇到了白板面试,面试官设置了限制,禁止使用StringBuilder并内置功能。

答案 12 :(得分:0)

当然,这是最有效的方法:

String reversed = new StringBuilder(str).reverse().toString();

但是,如果您不喜欢使用它,那么我建议您这样做:

public String reverseString(String str)
{
    String output = "";
    int len = str.length();
    for(int k = 1; k <= str.length(); k++, len--)
    {
        output += str.substring(len-1,len);
    }
    return output;
}

答案 13 :(得分:0)

使用多个线程交换元素:

    final char[] strArray = str.toCharArray();

    IntStream.range(0, str.length() / 2).parallel().forEach(e -> {
        final char tmp = strArray[e];
        strArray[e] = strArray[str.length() - e - 1];
        strArray[str.length() - e - 1] = tmp;
    });
    return new String(strArray);

答案 14 :(得分:0)

public static string getReverse(string str)
{
    char[] ch = str.ToCharArray();
    string reverse = "";
    for (int i = str.Length - 1; i > -1; i--)
    {
        reverse += ch[i];
    }
    return reverse;
}

//using in-built method reverse of Array
public static string getReverseUsingBulidingFunction(string str)
{
    char[] s = str.ToCharArray();
    Array.Reverse(s);
    return new string(s);
}


public static void Main(string[] args)
{
    string str = "123";
    Console.WriteLine("The reverse string of '{0}' is: {1}",str,getReverse(str));
    Console.WriteLine("The reverse string of '{0}' is: {1}", str, getReverseUsingBulidingFunction(str));
    Console.ReadLine();
}

答案 15 :(得分:0)

char* rev(char* str)
    {
    int end= strlen(str)-1;
    int start = 0;

    while( start<end )
    {
    str[start] ^= str[end];
    str[end] ^= str[start];
    str[start]^= str[end];

    ++start;
    --end;
    }

    return str;
}

=========================

想知道它是如何工作的?

第一次操作:

x1 = x1 XOR x2

x1: 1   0   0
x2: 1   1   1
New x1: 0   1   1

第二次操作

x2 = x2 XOR x1

x1: 0   1   1
x2: 1   1   1
New x2: 1   0   0
//Notice that X2 has become X1 now

第三次操作:

x1 = x1 XOR x2
x1: 0   1   1
x2: 1   0   0
New x1: 1   1   1
//Notice that X1 became X2

答案 16 :(得分:0)

public static String Reverse(String word){
        String temp = "";
        char[] arr = word.toCharArray();
        for(int i = arr.length-1;i>=0;i--){
            temp = temp+arr[i];
        }
        return temp;
    }

答案 17 :(得分:0)

public static void main(String[] args){
    String string ="abcdefghijklmnopqrstuvwxyz";
    StringBuilder sb = new StringBuilder(string);
    sb.reverse();

    System.out.println(sb);
}

答案 18 :(得分:0)

一种变体可以是,交换元素。

int n = length - 1;
char []strArray = str.toCharArray();
for (int j = 0; j < n; j++) {
   char temp = strArray[j];
   char temp2 = strArray[n];
   strArray[j] = temp2;
   strArray[n] = temp;
   n--;
  }

答案 19 :(得分:0)

使用字符串:

String abc = "abcd";
int a= abc.length();

String reverse="";

for (int i=a-1;i>=0 ;i--)
{
    reverse= reverse + abc.charAt(i);
}
System.out.println("Reverse of String abcd using invert array is :"+reverse);

使用StringBuilder:

    String abc = "abcd";
    int a= abc.length();
    StringBuilder sb1 = new StringBuilder();

    for (int i=a-1;i>=0 ;i--)
    {
        sb1= sb1.append(abc.charAt(i));
    }
    System.out.println("Reverse of String abcd using StringBuilder is :"+sb1);

答案 20 :(得分:-2)

public static String reverseString(String str)
{
    StringBuilder sb = new StringBuilder();

    for (int i = str.length() - 1; i >= 0; i--)
    {
        sb.append(str[i]);
    }

    return sb.toString();
}