Determine if a string is a palindrome with C# .NET

Here comes another classic coding question that you might come across during an interview. Write a function that accepts a string and returns a boolean. The function must determine if the string is a palindrome. A string is a palindrome if it has the same value in both directions: forward and backward. Examples:

  • abba
  • qwertrewq
  • 1234321

In this post we’ll look at two different solutions, but there are certainly others. Also, we’ll implement case-sensitive solutions, i.e. the following will return false:

  • aBba
  • qWertrewq

The first solution is based on looping through the characters of the string. In each iteration we compare the characters on two extremes from the midpoint. The midpoint is simply the string length divided by 2. Say we have the following string of length 8 chars:

qwerrewq

The midpoint of this string is 4. We start by comparing the char at position 0 with the char at position length - 1, i.e. ‘q’ with ‘q’. Then we continue with position 1 and position length - 2, that is ‘w’ and ‘w’. We continue until we reach the midpoint, i.e. position 4 and compare ‘r’ with ‘r’. This is the end of the loop and the function returns true.

What if we have an odd number of characters in the string? The same algorithm will still work, here’s an example:

qwerewq

The midpoint is 3 in this case: 7 / 2 = 3.5 and .NET will turn it into 3 when boxing it into an integer. So we compare ‘q’ with ‘q’, then ‘w’ with ‘w’ and finally ‘e’ with ‘e’. We don’t need to worry about ‘r’, the char in the very middle is always symmetrical with itself.

Here’s all of that in code form:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Algorithms
{
    public class Palindrome
    {
        public bool IsPalindrome(string str)
        {
            return IsPalindromeWithLoop(str);
        }
        
        private bool IsPalindromeWithLoop(string str)
        {
            for (int i = 0; i < str.Length / 2; i++)
            {
                if (str[i] != str[str.Length - i - 1])
                {
                    return false;
                }
            }          

            return true;
        }
    }
}

…and here come a couple of unit tests:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Algorithms.Tests
{
    [TestClass]
    public class PalindromeTests
    {
        [TestMethod]
        public void IsPalindromeTest()
        {
            Palindrome palindrome = new Palindrome();
            Assert.IsTrue(palindrome.IsPalindrome("abba"));
            Assert.IsTrue(palindrome.IsPalindrome("qwewq"));
            Assert.IsTrue(palindrome.IsPalindrome("12344321"));
            Assert.IsFalse(palindrome.IsPalindrome("   hehe  "));
            Assert.IsFalse(palindrome.IsPalindrome("Hello olleh")); //case sensitive!!
            Assert.IsTrue(palindrome.IsPalindrome("   abba   "));
        }
    }
}

The second solution is based on a simple string comparison. We take the incoming string, reverse it and compare the original with the reversed string:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Algorithms
{
    public class Palindrome
    {
        public bool IsPalindrome(string str)
        {
            return IsPalindromeWithReverse(str);
            //return IsPalindromeWithLoop(str);
        }

        private bool IsPalindromeWithReverse(string str)
        {
            if (str == null) return false;
            var reverse = string.Join("", str.Reverse());
            return str == reverse;
        }        
    }
}

The Reverse() extension method creates an IEnumerable of chars, i.e. not a string. We take that char collection and join its elements into a string. The empty string in the string.Join function is the delimiter, meaning that we don’t want to put anything in between the chars when joining them. Finally we compare the two strings as the return value of the function.

Run the unit tests, they will pass as expected.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

HarsH ReaLiTy

A Good Blog is Hard to Find

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: