web-dev-qa-db-ja.com

Javaで文字列を反転させるための最も効率的なアルゴリズムは何ですか?

Javaで文字列を逆にする最も効率的な方法は何ですか?何らかのxor演算子を使用する必要がありますか?簡単な方法は、すべての文字をスタックに入れて再び文字列に戻すことですが、それが非常に効率的な方法だとは思いません。

また、Javaの組み込み関数を使用するように言わないでください。私は、効率的な機能を使用しないようにする方法を学ぶことに興味がありますが、それがなぜ効率的であるか、またはどのように構築されるかを知りません。

35
Hultner

最も効率的な方法を知りたいと言いますが、これを行うための標準的な組み込み方法を知りたくありません。それから私はあなたに言います:RTSL(ソースを読む、ルーク):

AbstractStringBuilder#reverse のソースコードを確認します。これは、StringBuilder#reverseによって呼び出されます。堅牢な逆操作では考慮していなかったような処理を行うに違いありません。

50
Tom

以下は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);
}
37
Simon Nickerson

あなたはそれを簡単な方法でやりたくないと言いましたが、それらのグーグルのためにあなたは StringBuilder.reverse を使うべきです:

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

自分で実装する必要がある場合は、文字を逆の順序で繰り返し、StringBuilderに追加します。サロゲートペアが存在する(または存在する可能性がある)場合、これらを逆にしないでください。上記のメソッドはこれを自動的に行うため、可能であれば使用する必要があります。

20
Mark Byers

古い投稿と質問ですが、再帰に関する回答はまだありませんでした。組み込みのjdk関数を中継せずに、指定された文字列sを逆順にする方法

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

`

8
cocoper

最速の方法は、StringBuilderまたはStringBufferクラスでreverse()メソッドを使用することです:)

自分で実装する場合は、文字配列を取得し、2番目の文字配列を割り当てて文字を移動できます。擬似コードでは、次のようになります。

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
rsp

効率的アルゴリズムが必要だと言ったとき、どういう意味なのかよくわかりません。

私が考えることができる文字列を逆にする方法は次のとおりです(それらはすべて他の答えですでに言及されています):

  1. スタックを使用します(あなたのアイデア)。

  2. 元の文字列から空の文字列/ StringBuilder/char []に文字を1つずつ逆順に追加して、新しい逆文字列を作成します。

  3. Stringの前半のすべての文字を後半の対応する位置と交換します(つまり、i番目の文字は(length-i-1)番目の文字と交換されます)。

問題は、それらすべてが同じ実行時の複雑さ:O(N)を持っていることです。したがって、Nの非常に大きな値(つまり、非常に大きな文字列)について、いずれかが他のものよりも大幅に優れていると実際に主張することはできません。

3番目の方法には1つのことがあり、他の2つにはO(N)余分なスペース(スタックまたは新しい文字列用)が必要ですが、代わりにスワップを実行できます。 Javaでは不変であるため、新しく作成されたStringBuilder/char []でスワップを実行する必要があり、したがってO(N)余分なスペースが必要になります。

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

    }
}
3
abiolaaye
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);
}
2
Kuldeep Singh

パフォーマンスの問題が本当にない場合は、最も読みやすいソリューションを使用する必要があります。

StringUtils.reverse("Hello World");
2
Marcin Szymczak

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

確認してください。乾杯!!

1
Vivek

組み込み関数を使用したくない場合は、文字列をそのコンポーネント部分(文字の配列)に戻す必要があります。

配列を逆にする最も効率的な方法は何ですか?実際のこの質問に対する答えは、メモリ使用量(非常に大きな文字列の場合)にも依存しますが、理論的にはこれらの場合の効率は配列アクセスで測定されます。

最も簡単な方法は、新しい配列を作成し、元の配列を逆反復しながら新しい値を返すときに遭遇する値を入力することです。 (一時変数を使用すると、Simon Nickersonsの回答のように、追加の配列なしでこれを行うこともできます)。

このようにして、n個の要素を持つ配列の各要素に1回だけアクセスします。したがって、O(n)の効率が得られます。

1
NomeN
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

2番目の操作

x2 = x2 XOR x1

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

3番目の操作:

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

文字列を使用:

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
jags
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
Dipitak

1つのバリエーションとして、要素の交換があります。

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
Naren
public static void main(String[] args){
    String string ="abcdefghijklmnopqrstuvwxyz";
    StringBuilder sb = new StringBuilder(string);
    sb.reverse();

    System.out.println(sb);
}
0
Dan

複数のスレッドを使用して要素を交換する:

    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
user3666072

もちろん、これは最も効率的な方法です。

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;
}
0
GlennTheAlien
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
saad