Efficiently reverse the order of the words (not characters) in an array of characters

前端 未结 21 1800
[愿得一人]
[愿得一人] 2020-11-28 04:40

Given an array of characters which forms a sentence of words, give an efficient algorithm to reverse the order of the words (not characters) in it.

Example input and

相关标签:
21条回答
  • 2020-11-28 04:55

    @Daren Thomas

    Implementation of your algorithm (O(N) in time, O(1) in space) in D (Digital Mars):

    #!/usr/bin/dmd -run
    /**
     * to compile & run:
     * $ dmd -run reverse_words.d
     * to optimize:
     * $ dmd -O -inline -release reverse_words.d
     */
    import std.algorithm: reverse;
    import std.stdio: writeln;
    import std.string: find;
    
    void reverse_words(char[] str) {
      // reverse whole string
      reverse(str);
    
      // reverse each word
      for (auto i = 0; (i = find(str, " ")) != -1; str = str[i + 1..length])
        reverse(str[0..i]);
    
      // reverse last word
      reverse(str);
    }
    
    void main() {
      char[] str = cast(char[])("this is a string");
      writeln(str);
      reverse_words(str);
      writeln(str);
    }
    

    Output:

    this is a string
    string a is this
    0 讨论(0)
  • 2020-11-28 04:56

    A solution in C/C++:

    void swap(char* str, int i, int j){
        char t = str[i];
        str[i] = str[j];
        str[j] = t;
    }
    
    void reverse_string(char* str, int length){
        for(int i=0; i<length/2; i++){
            swap(str, i, length-i-1);
        }
    }
    void reverse_words(char* str){
        int l = strlen(str);
        //Reverse string
        reverse_string(str,strlen(str));
        int p=0;
        //Find word boundaries and reverse word by word
        for(int i=0; i<l; i++){
            if(str[i] == ' '){
                reverse_string(&str[p], i-p);
                p=i+1;
            }
        }
        //Finally reverse the last word.
        reverse_string(&str[p], l-p);
    }
    

    This should be O(n) in time and O(1) in space.

    Edit: Cleaned it up a bit.

    The first pass over the string is obviously O(n/2) = O(n). The second pass is O(n + combined length of all words / 2) = O(n + n/2) = O(n), which makes this an O(n) algorithm.

    0 讨论(0)
  • 2020-11-28 04:58

    Efficient in terms of my time: took under 2 minutes to write in REBOL:

    reverse_words: func [s [string!]] [form reverse parse s none]
    

    Try it out: reverse_words "this is a string" "string a is this"

    0 讨论(0)
  • 2020-11-28 04:59

    THIS PROGRAM IS TO REVERSE THE SENTENCE USING POINTERS IN "C language" By Vasantha kumar & Sundaramoorthy from KONGU ENGG COLLEGE, Erode.

    NOTE: Sentence must end with dot(.) because NULL character is not assigned automatically at the end of the sentence*

     #include<stdio.h>
     #include<string.h>
    
    int main()
    {
    char *p,*s="this is good.",*t;
    int i,j,a,l,count=0;
    
    l=strlen(s);
    
    p=&s[l-1];
    
    t=&s[-1];
    while(*t)
       {
          if(*t==' ')
         count++;
         t++;
       }
       a=count;
      while(l!=0)
       {
    for(i=0;*p!=' '&&t!=p;p--,i++);
       p++;
    
      for(;((*p)!='.')&&(*p!=' ');p++)
        printf("%c",*p);
      printf(" ");
      if(a==count)
       {
         p=p-i-1;
         l=l-i;
       }
      else
       {
         p=p-i-2;
         l=l-i-1;
       }
    
    count--;
      }
    
    return 0;  
    }
    
    0 讨论(0)
  • 2020-11-28 05:01

    Here is my answer. No library calls and no temp data structures.

    #include <stdio.h>
    
    void reverse(char* string, int length){
        int i;
        for (i = 0; i < length/2; i++){
            string[length - 1 - i] ^= string[i] ;
            string[i] ^= string[length - 1 - i];
            string[length - 1 - i] ^= string[i];
        }   
    }
    
    int main () {
    char string[] = "This is a test string";
    char *ptr;
    int i = 0;
    int word = 0;
    ptr = (char *)&string;
    printf("%s\n", string);
    int length=0;
    while (*ptr++){
        ++length;
    }
    reverse(string, length);
    printf("%s\n", string);
    
    for (i=0;i<length;i++){
        if(string[i] == ' '){
           reverse(&string[word], i-word);
           word = i+1;
           }
    }   
    reverse(&string[word], i-word); //for last word             
    printf("\n%s\n", string);
    return 0;
    }
    
    0 讨论(0)
  • 2020-11-28 05:02

    pushing a string onto a stack and then popping it off - is that still O(1)? essentially, that is the same as using split()...

    Doesn't O(1) mean in-place? This task gets easy if we can just append strings and stuff, but that uses space...

    EDIT: Thomas Watnedal is right. The following algorithm is O(n) in time and O(1) in space:

    1. reverse string in-place (first iteration over string)
    2. reverse each (reversed) word in-place (another two iterations over string)
      1. find first word boundary
      2. reverse inside this word boundary
      3. repeat for next word until finished

    I guess we would need to prove that step 2 is really only O(2n)...

    0 讨论(0)
提交回复
热议问题