Stuck Finding Bug in LeetCode Question Solution

60 views Asked by At

The problem is simple: take a string, and reverse the position of ONLY letters (lower or uppercase). Leave any special characters where they are. My solution:

char * reverseOnlyLetters(char * S){
    
    int Len = strlen(S);
    char *StrBeg, *StrEnd, tempCh;
    bool FoundStart = 0, FoundEnd = 0;
    
    StrBeg = S;
    StrEnd = S + (Len - 1);
    
    for (int i = 0; i < (Len/2); i++)
    {
        if (((*StrBeg>= 'A') && (*StrBeg <= 'Z')) || ((*StrBeg >= 'a') && (*StrBeg <= 'z')))            
        {
            FoundStart = 1;
        }
        else
        {
            StrBeg++;
        }
        
        if (((*StrEnd >= 'A') && (*StrEnd <= 'Z')) || ((*StrEnd >= 'a') && (*StrEnd <= 'z')))            
        {
            FoundEnd = 1;
        }
        else
        {
            StrEnd--;
        }
        
        if(FoundStart && FoundEnd)
        {
            tempCh = *StrEnd;
            *StrEnd = *StrBeg;
            *StrBeg = tempCh;
            
            StrBeg++;
            StrEnd--;
            
            FoundStart = 0;
            FoundEnd = 0;
        }
            
    }

    return S;
}

The issue is a testcase like "a-bC-dEf-ghIj" fails; the "E" and the "f" in the middle either don't get swapped at all, or (as I suspect), get swapped, but then get swapped BACK. Anyone see what I'm doing wrong?

2

There are 2 answers

0
Vlad from Moscow On

The approach using this for loop

for (int i = 0; i < (Len/2); i++)

is incorrect. Let's assume that the string is "@AB". The result string will look like "@BA"

But using your loop you will have (as Len / 2 is equal to 1)

for (int i = 0; i < 1; i++)

In the first and single iteration of the loop the pointer StrBeg will be incremented

StrBeg++;

because the pointed character is not a letter.

So nothing will be reversed.

The function can be written simpler the following way

#include <stdio.h>
#include <string.h>
#include <ctype.h>

char * reverse_letters( char *s )
{
    for ( char *first = s, *last = s + strlen( s ); first < last; ++first )
    {
        while ( first != last && !isalpha( ( unsigned char )*first ) ) ++first;
        while ( last != first && !isalpha( ( unsigned char )*--last ) );
        
        if ( first != last )
        {
            char c = *first;
            *first = *last;
            *last = c;
        }
    }
    
    return s;
}

int main( void ) 
{
    char s[] = "one, two, three";
    puts( s );
    puts( reverse_letters( s ) );

    char s1[] = "@AB";
    puts( s1 );
    puts( reverse_letters( s1 ) );
}   

The program output is

one, two, three
eer, hto, wteno
@AB
@BA
0
Filip Emanuel Drexler On

Problem is this for (int i = 0; i < (Len/2); i++). If lenght of string is even, it's ok, but in case it's even it doesn't go through the middle character. E in this "a-bC-dEf-ghIj" case, so it can't switch it with f.