1

Recently I have been asked in a discussion to write an algorithm to implement reverse of words of a sentence (Not reverse of whole sentence) without using string operations such as Split/Replace/Reverse/Join except ToCharArray and Length. The below is what I could devise in 5min of time. Though the algorithm is working fine, it seems bit ugly style of implementation. Can some body help me by polishing the code.

string ReverseWords(string s)
{
    string reverseString = string.Empty;
    string word = string.Empty;

    var chars = s.ToCharArray();
    List<ArrayList> words = new List<ArrayList>();
    ArrayList addedChars = new ArrayList();
    Char[] reversedChars = new Char[chars.Length];
    int i = 1;
    foreach (char c in chars)
    {
        if (c != ' ')
        {
            addedChars.Add(c);
        }
        else
        {
            words.Add(new ArrayList(addedChars));
            addedChars.Clear();
        }
        if (i == s.Length)
        {
            words.Add(new ArrayList(addedChars));
            addedChars.Clear();
        }
        i++;
    }
    foreach (ArrayList a in words)
    {
        for (int counter = a.Count - 1; counter >= 0; counter--)
        {
            reverseString += a[counter];
        }
        if(reverseString.Length < s.Length)
            reverseString += " ";
    }
    return reverseString;
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
gee'K'iran
  • 431
  • 2
  • 7
  • 21

10 Answers10

8

There is a relatively elegant solution which uses a LIFO stack.
Question however sounds like homework, so I'll only provide the pseudo code.

currWord = new LIFO stack of characters
while (! end of string/array)
{
  c = next character in string/array
  if (c == some_white_space_character) {
     while (currWord not empty) {
       c2 = currWord.pop()
       print(c2)
     }
     print(c)
  }
  else
    currWord.push(c)
}
mjv
  • 73,152
  • 14
  • 113
  • 156
6

This is somewhat simpler:

string inp = "hai how are you?";
StringBuilder strb = new StringBuilder();
List<char> charlist = new List<char>();
for (int c = 0; c < inp.Length; c++ )
{

    if (inp[c] == ' ' || c == inp.Length - 1)
    {
        if (c == inp.Length - 1)
            charlist.Add(inp[c]);
        for (int i = charlist.Count - 1; i >= 0; i--)
            strb.Append(charlist[i]);

        strb.Append(' ');
        charlist = new List<char>();
    }
    else
        charlist.Add(inp[c]);
}
string output = strb.ToString();
Uthistran Selvaraj
  • 1,371
  • 1
  • 12
  • 31
2

Kind of a polished version:-

string words = "hi! how are you!";
string reversedWords = "";

List<int> spaceEncounter = new List<int>();
spaceEncounter.Add(words.Length - 1);

for (int i = words.Length - 1; i > 0; i--)
{ 
    if(words[i].Equals(' '))
    {
        spaceEncounter.Add(i);

        for (int j = i+1; j < spaceEncounter[spaceEncounter.Count - 2]; j++)
            reversedWords += words[j];

        reversedWords += " ";
    }
}

for (int i = 0; i < spaceEncounter[spaceEncounter.Count - 1]; i++)
    reversedWords += words[i];    
1

There is a small bug in your code. Due to this, the output string would be displayed as yo are how hi!, given the input string hi! how are you. It's truncating the last char of the last word.

Change this:

spaceEncounter.Add(words.Length - 1);

To:

spaceEncounter.Add(words.Length);
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Sushant
  • 11
  • 1
1

Well, you didn't say anything about the other LINQ extension methods :)

static string ReverseWordsWithoutSplit(string input)
{
    var n = 0;
    var words = input.GroupBy(curr => curr == ' ' ? n++ : n);

    return words.Reverse().Aggregate("", (total, curr) => total + string.Concat(curr.TakeWhile(c => c != ' ')) + ' ');
}
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
  • :-) Condition is that I shouldn't use framework features such as linq. Thanks for the answer though. It's clean and nice. – gee'K'iran Oct 24 '16 at 14:24
1

One of the Easiest Answer is as given Below please go through it,

public static string ReversewordString(string Name)
    {
        string output="";
        char[] str = Name.ToCharArray();
        for (int i = str.Length - 1; i >= 0; i--)
        {
            if (str[i] == ' ')
            {
                output = output + " ";
                for (int j = i + 1; j < str.Length; j++)
                {
                    if (str[j] == ' ')
                    {
                        break;
                    }
                    output=output+ str[j];
                }
            }
            if (i == 0)
            {
                output = output +" ";
                int k = 0;
                do
                {
                    output = output + str[k];
                    k++;
                } while (str[k] != ' ');
            }
        }
        return output;
    }
XORG_99
  • 180
  • 4
  • 15
0
        string temp = string.Empty;
        string reversedString = string.Empty;

        foreach (var currentCharacter in testSentence)
        {
            if (currentCharacter != ' ')
            {
                temp = temp + currentCharacter;
            }
            else
            {
                reversedString = temp + " " + reversedString;
                temp = string.Empty;
            }
        }
        reversedString = temp + " " + reversedString;
bitbyte
  • 483
  • 1
  • 6
  • 10
0

This version works in-place, without any intermediate data structures. First, it reverses the characters in each word. "me too" => "em oot". Then it reverses the whole string: "em oot" => "too me".

    public static string ReverseWords(string s)
    {
        if (string.IsNullOrEmpty(s))
            return s;

        char[] chars = s.ToCharArray();
        int wordStartIndex = -1;

        for (int i = 0; i < chars.Length; i++)
        {
            if (!Char.IsWhiteSpace(chars[i]) && wordStartIndex < 0)
            {
                // Remember word start index
                wordStartIndex = i;
            }
            else
            if (wordStartIndex >= 0 && (i == chars.Length-1 || Char.IsWhiteSpace(chars[i + 1]))) {
                // End of word detected, reverse the chacacters in the word range
                ReverseRange(chars, wordStartIndex, i);

                // The current word is complete, reset the start index  
                wordStartIndex = -1;
            }
        }

        // Reverse all chars in the string
        ReverseRange(chars, 0, chars.Length - 1);

        return new string(chars);
    }

    // Helper
    private static void ReverseRange(char[] chars, int startIndex, int endIndex)
    {
        for(int i = 0; i <= (endIndex - startIndex) / 2; i++)
        {
            char tmp = chars[startIndex + i];
            chars[startIndex + i] = chars[endIndex - i];
            chars[endIndex - i] = tmp;
        }            
    }
  • Hi there, i know this is an old question but i have been looking for an in place algorithm for the above question. Your solution is the one that closely mimicks mine. I want to know if you have any references that can substantiate your claim that this is indeed in place? It definitely agrees with my understanding of in place but i am concerned at our use of temp variables which, to be fair, are also using memory... – prismeyez83 Jul 15 '19 at 08:44
0

How about a simple recursive function that checks for a " " and then substring accordingly?

    private static string rev(string inSent) { 
        if(inSent.IndexOf(" ") != -1) 
        { 
            int space = inSent.IndexOf(" "); 
            System.Text.StringBuilder st = new System.Text.StringBuilder(inSent.Substring(space+1)); 
            return rev(st.ToString()) + " " + inSent.Substring(0, space); 
        } 
        else 
        { 
            return inSent; 
        } 
    }
0

use stack in C#

string str = "ABCDEFG";
Stack<char> stack=new Stack<char>();
foreach (var c in str)
{
    stack.Push(c);
}
char[] chars=new char[stack.Count];
for (int i = 0; i < chars.Length; i++)
{
    chars[i]=stack.Pop();
}
var result=new string(chars); //GFEDCBA
Ali Bayat
  • 3,561
  • 2
  • 42
  • 43