web-dev-qa-db-fra.com

Quel est l'algorithme le plus efficace pour inverser une chaîne en Java?

Quel est le moyen le plus efficace d'inverser une chaîne en Java? Devrais-je utiliser une sorte d'opérateur xor? Le moyen le plus simple serait de mettre tous les caractères dans une pile et de les remettre dans une chaîne, mais je doute que ce soit une façon très efficace de le faire. 

Et s'il vous plaît, ne me dites pas d'utiliser certaines fonctions intégrées en Java. Je suis intéressé à apprendre à le faire pour ne pas utiliser une fonction efficace sans savoir pourquoi elle est efficace ou comment elle est construite. 

34
Hultner

Vous dites que vous voulez connaître le moyen le plus efficace et que vous ne voulez pas connaître une manière standard de le faire. Alors je vous dis: RTSL (lisez la source, luke):

Consultez le code source pour AbstractStringBuilder # reverse , appelé par StringBuilder # reverse. Je parie que cela fait des choses que vous n'auriez pas considérées comme une opération inverse robuste.

49
Tom

Ce qui suit ne traite pas des paires de substitution 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);
}
35
Simon Nickerson

Vous avez dit que vous ne voulez pas le faire facilement, mais pour ceux qui recherchent Google, vous devez utiliser StringBuilder.reverse :

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

Si vous avez besoin de l'implémenter vous-même, parcourez les caractères dans l'ordre inverse et ajoutez-les à un StringBuilder. Vous devez faire attention s'il y a (ou peut être) des paires de substitution, car elles ne devraient pas être inversées. La méthode présentée ci-dessus le fait automatiquement pour vous. C'est pourquoi vous devriez l'utiliser si possible.

20
Mark Byers

Un vieux post et une question, mais ne trouvaient toujours pas de réponses concernant la récursion. Méthode récursive inverse la chaîne donnée s, sans relayer les fonctions jdk intégrées

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

`

8
cocoper

Le moyen le plus rapide serait d’utiliser la méthode reverse() sur les classes StringBuilder ou StringBuffer :)

Si vous voulez l'implémenter vous-même, vous pouvez obtenir le tableau de caractères, allouer un second tableau de caractères et déplacer les caractères. Dans le pseudo-code, cela ressemble à ceci:

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

Vous pouvez également exécuter la moitié de la longueur du tableau et échanger les caractères, les vérifications impliquées ralentiront probablement les choses.

5
rsp

Je ne suis pas vraiment sûr de ce que vous voulez dire quand vous dites que vous avez besoin d'un algorithme efficace.

Les manières d'inverser une chaîne que je peux penser sont (elles sont toutes déjà mentionnées dans d'autres réponses):

  1. Utilisez une pile (votre idée).

  2. Créez une nouvelle chaîne inversée en ajoutant des caractères un par un dans l'ordre inverse de la chaîne d'origine à une chaîne vide/StringBuilder/char [].

  3. Échangez tous les caractères dans la première moitié de la chaîne avec la position correspondante dans la dernière moitié (c.-à-d. Que le ieme caractère est échangé avec le (longueur-i-1) ème caractère).

Le fait est que tous ont le même complexité d'exécution: O (N). Ainsi, on ne peut pas vraiment affirmer que l’un est significativement meilleur que les autres pour les très grandes valeurs de N (c’est-à-dire les très grandes chaînes).

La troisième méthode a une chose pour elle, les deux autres nécessitent O(N) d'espace supplémentaire (pour la pile ou la nouvelle chaîne), alors qu'elle peut effectuer des permutations sur place. Mais les chaînes de caractères étant immuables en Java, vous devez de toute façon effectuer des permutations sur un StringBuilder/char [] nouvellement créé et ainsi avoir besoin de plus d'espace 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

Je pense que si vous n’avez VRAIMENT pas de problème de performances, vous devriez simplement choisir la solution la plus lisible, à savoir:

StringUtils.reverse("Hello World");
2
Marcin Szymczak
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;
}

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

Vous vous demandez comment cela fonctionne?

Première opération: 

x1 = x1 XOR x2

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

Deuxième opération 

x2 = x2 XOR x1

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

Troisième opération: 

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

Je le ferais simplement de cette façon sans utiliser une seule fonction util. Juste la classe String est suffisante.

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

Vérifie ça. À votre santé!!

1
Vivek

Si vous ne souhaitez utiliser aucune fonction intégrée, vous devez revenir en arrière avec la chaîne en ses composants: un tableau de caractères.

Maintenant, la question est de savoir quel est le moyen le plus efficace d’inverser un tableau. Dans la pratique, la réponse à cette question dépend également de l'utilisation de la mémoire (pour les très grandes chaînes), mais en théorie, l'efficacité est mesurée dans les cas d'accès aux tableaux. 

Le moyen le plus simple consiste à créer un nouveau tableau et à le renseigner avec les valeurs que vous rencontrerez lors d'une itération inverse sur le tableau d'origine et de renvoyer le nouveau tableau. (Bien qu'avec une variable temporaire, vous pouvez également le faire sans un tableau supplémentaire, comme dans la réponse de Simon Nickersons).

De cette façon, vous accédez à chaque élément exactement une fois pour un tableau de n éléments. Donnant ainsi une efficacité de O (n). 

1
NomeN

Utilisation de chaîne: 

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

Utilisation de 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

Une variante peut être, permuter les éléments. 

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

Utilisation de plusieurs threads pour échanger les éléments:

    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

Bien sûr, c’est le moyen le plus efficace:

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

Mais si vous n'aimez pas utiliser cela, je vous recommande plutôt ceci:

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