'Check whether string in palindrome : C# code efficiency
I am coming from C background and recently started writing in C# so please don't mind if my question seems somewhat basic. Basically, i want to write a function which will return true if string is palindrome and false if not.
The string may contain characters like space, ',', ':' which i have to ignore. I have written the code as below
static bool IsPalindrome(string s)
{
s = s.Replace(" ", "");
s = s.Replace(",", "");
s = s.Replace(":", "");
int j = s.Length - 1;
for(int i = 0; i < s.Length/2; i++)
{
if(s[i].ToString().Equals(s[j].ToString(),StringComparison.InvariantCultureIgnoreCase))
{
j--;
}
else
{
return false;
}
}
return true;
}
where the function will be invoked with the following string
string s = "A man, a plan, a canal: Panama";
I read in the documentation that in C#, string are immutable so each time i do a operation like replace or ToString, a new copy is getting created.
So i wanted to check that i). Is this code efficient? ii). If not, how to make it more efficient.
Solution 1:[1]
You don't need to use .Replace
or create new strings, you can just skip the unwanted characters as you compare.
static bool IsPalindrome(string s)
{
var i = 0;
var j = s.Length - 1;
while (j > i)
{
if (s[i] == ':' || s[i] == ',' || s[i] == ' ')
{
i++;
continue;
}
if (s[j] == ':' || s[j] == ',' || s[j] == ' ')
{
j--;
continue;
}
if (char.ToUpperInvariant(s[i++]) != char.ToUpperInvariant(s[j--])) return false;
}
return true;
}
Solution 2:[2]
This would be more readable approach for the Plaindrome detection comparing to the for loop
you have written:
A short approach but not necessary efficient due to Array.Reverse
which Reverses the order of the elements :
static bool IsPalindrome(string s)
{
s = s.Replace(" ", "");
s = s.Replace(",", "");
s = s.Replace(":", "");
char[] array = s.ToCharArray();
Array.Reverse(array);
string backwards = new string(array);
return s == backwards;
}
A more efficient approach which requires more lines of coding would be :
static bool IsPalindrome(string s)
{
s = s.Replace(" ", "");
s = s.Replace(",", "");
s = s.Replace(":", "");
int i = 0;
int j = s.Length - 1;
while (i < j)
{
if (s[i].ToString().ToLower() != s[j].ToString().ToLower())
return false;
i++;
j--;
}
return true;
}
Another approach similar to the 2nd one but without the needs of converting the char
into String
for comparison:
static bool IsPalindrome(string s)
{
s = s.Replace(" ", "");
s = s.Replace(",", "");
s = s.Replace(":", "");
int i = 0;
int j = s.Length - 1;
while (i < j)
{
if (!char.ToLower(s[i]).Equals(char.ToLower(s[j])))
return false;
i++;
j--;
}
return true;
}
Solution 3:[3]
The obligatory short but inefficient LINQ solution:
static bool IsPalindrome(string s)
{
return s.Where(Char.IsLetterOrDigit).Take(s.Length / 2)
.SequenceEqual(s.Reverse().Where(Char.IsLetterOrDigit).Take(s.Length / 2));
}
Solution 4:[4]
This solution should be familiar to you if you're coming from a C background. There's no need to allocate a bunch of new strings; just ignore non-letter characters.
There doesn't seem to be a case-insensitive comparison of char
values in .NET, so this code assumes that ToLower(...)
with the current culture is sufficient.
public static bool EqualsIgnoreCase(char c1, char c2)
{
var culture = System.Globalization.CultureInfo.CurrentCulture;
return Char.ToLower(c1, culture) == Char.ToLower(c2, culture);
}
public static bool IsPalindrome(string s)
{
switch (s?.Length ?? 0)
{
case 0:
return false;
case 1:
return true;
case 2:
return EqualsIgnoreCase(s[0], s[1]);
case 3:
return EqualsIgnoreCase(s[0], s[2]);
}
var firstIndex = 0;
var lastIndex = s.Length - 1;
// todo: this probably falls on its face for a string with only non-letters
do
{
while (!Char.IsLetter(s[firstIndex]))
++firstIndex;
while (!Char.IsLetter(s[lastIndex]))
--lastIndex;
if (!EqualsIgnoreCase(s[firstIndex++], s[lastIndex--]))
return false;
} while (firstIndex < lastIndex);
return true;
}
Solution 5:[5]
This program upon execution counts the number of palindromes words/numbers that are present in the sentence and displays them.
class Program
{
static void Main(string[] args)
{
Palindrome("Lorem ipsum dolor sit amet, voluptate mom velit omo esse cillum dolore eu fugiatnulla pariatur. Excepteur non proident est laborum.");
}
static void Palindrome(string sentence)
{
var arr = sentence.Split(" ");
List<string> palindromes = new List<string>();
int count = 0;
foreach (var str in arr)
{
string rev = string.Empty;
for (int i = str.Length-1; i >= 0; i--)
{
rev = rev+str[i];
}
if (str.Equals(rev,StringComparison.OrdinalIgnoreCase))
{
palindromes.Add(rev);
count++;
}
}
Console.WriteLine($"Total palindromes: {count}");
foreach (var palindrome in palindromes)
{
Console.Write($"'{palindrome}' ");
}
Console.ReadKey();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ahmad Ibrahim |
Solution 2 | |
Solution 3 | Theodor Zoulias |
Solution 4 | |
Solution 5 | Abah Joseph Israel |