我来自C的背景,最近开始用C#编写,所以请不要介意我的问题似乎有些基本。基本上,我想编写一个函数,如果字符串是回文,则返回true,否则返回false。
该字符串可能包含我必须忽略的字符,例如空格,“,”,“:”。我写了下面的代码
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;
}
将使用以下字符串
调用函数string s = "A man, a plan, a canal: Panama";
我在文档中读到,在C#中,字符串是不可变的,因此每次我执行诸如replace或ToString之类的操作时,都会创建一个新副本。
所以我想检查一下 一世)。此代码有效吗? ii)。如果没有,如何提高效率。
答案 0 :(得分:2)
您无需使用.Replace
或创建新字符串,只需在比较时跳过不需要的字符即可。
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;
}
答案 1 :(得分:1)
与您编写的for loop
相比,这是一种更易于阅读的原告检测方法:
一种简短的方法,但由于Array.Reverse
会颠倒元素的顺序,因此不一定有效:
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;
}
需要更多代码行的更有效方法是:
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;
}
另一种类似于第二种方法,但不需要将char
转换为String
进行比较:
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;
}
答案 2 :(得分:0)
如果您来自C背景,则应该熟悉此解决方案。无需分配一堆新字符串。只需忽略非字母字符即可。
.NET中似乎没有char
值的大小写不敏感的比较,因此此代码假定ToLower(...)
与当前区域性是足够的。
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;
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;
}
答案 3 :(得分:0)
强制性的但效率低的LINQ解决方案:
static bool IsPalindrome(string s)
{
return s.Where(Char.IsLetterOrDigit).Take(s.Length / 2)
.SequenceEqual(s.Reverse().Where(Char.IsLetterOrDigit).Take(s.Length / 2));
}