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

问题描述 投票:34回答:21

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

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

java algorithm string performance
21个回答
49
投票

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

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


1
投票

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

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

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

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


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();
    }
}

核实。干杯!!


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);

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--;
  }

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

    System.out.println(sb);
}

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;
    }

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;
}

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

Wondering how it works?

第一次操作:

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

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();
}

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);

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;
}

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);
}

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和内置功能。


-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();
}

20
投票

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

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

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


8
投票

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

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

`


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);
}

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


3
投票

当你说你需要一个有效的算法时,我不确定你的意思。

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

  1. 使用堆栈(您的想法)。
  2. 通过从原始String以相反的顺序逐个添加字符到空字符串/ StringBuilder / char []来创建新的反向字符串。
  3. 将字符串前半部分中的所有字符与其后半部分中的相应位置交换(即第i个字符与第(length-i-1)字符交换)。

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

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


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]);
       }

    }
}

2
投票

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

StringUtils.reverse("Hello World");

2
投票
private static String reverse(String str) {
    int i = 0;
    int j = str.length()-1;
    char []c = str.toCharArray();
    while(i <= j){
        char t = str.charAt(i);
        c[i] = str.charAt(j);
        c[j]=t;
        i++;
        j--;
    }
    return new String(c);
}
© www.soinside.com 2019 - 2024. All rights reserved.