[英]How can check anagram strings in C#
給定兩個字符串 A 和 B,檢查它們是否是字謎。
如果可以通過重新排列另一個字符串的字母來獲得一個字符串,則稱兩個字符串是字謎。
字謎的例子是
dog, god
abac, baac
123, 312
abab, aaba
和dab, baad
不是字謎。
輸入 :
輸入的第一行是測試用例的數量T。后面是T行,每行有兩個空格分隔的字符串A和B;
輸出
對於每個測試用例,如果它們是字謎,則打印“YES”,否則打印“NO”。 (不帶引號)
約束
`
Sample Input Sample Output
------------------------------------
3 YES
abcd bcda NO
bad daa YES
a1b2c3 abc123 NO
我們應該怎么做 ?
bool anagramChecker(string first, string second)
{
if(first.Length != second.Length)
return false;
if(first == second)
return true;//or false: Don't know whether a string counts as an anagram of itself
Dictionary<char, int> pool = new Dictionary<char, int>();
foreach(char element in first.ToCharArray()) //fill the dictionary with that available chars and count them up
{
if(pool.ContainsKey(element))
pool[element]++;
else
pool.Add(element, 1);
}
foreach(char element in second.ToCharArray()) //take them out again
{
if(!pool.ContainsKey(element)) //if a char isn't there at all; we're out
return false;
if(--pool[element] == 0) //if a count is less than zero after decrement; we're out
pool.Remove(element);
}
return pool.Count == 0;
}
這是您的解決方案嗎?
string a = "abcd";
string b = "bcda"; // bad daa a1b2c3 abc123
string aa = String.Concat(a.OrderBy(c => c));
string bb = String.Concat(b.OrderBy(c => c));
if (aa == bb)
{
Console.WriteLine("YES");
}
else
{
Console.WriteLine("NO");
}
或更短
if (String.Concat(a.OrderBy(c => c)).Equals(String.Concat(b.OrderBy(c => c))) ...
有快速的方法和簡單的方法:
void Test()
{
string a = "abccabccabccabccabccabccabccabccabccabccabccabccabccabccabccabcc";
string b = "bcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcacbcac";
IsAnagramSimple(a, b);
IsAnagramFast(a, b);
}
private bool IsAnagramSimple(string a, string b)
{
return a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c));
}
private bool IsAnagramFast(string a, string b)
{
if (a.Length != b.Length)
{
return false;
}
var aFrequency = CalculateFrequency(a);
var bFrequency = CalculateFrequency(b);
foreach (var key in aFrequency.Keys)
{
if (!bFrequency.ContainsKey(key)) return false;
if (aFrequency[key] != bFrequency[key]) return false;
}
return true;
}
private Dictionary<char, int> CalculateFrequency(string input)
{
var frequency = new Dictionary<char, int>();
foreach (var c in input)
{
if (!frequency.ContainsKey(c))
{
frequency.Add(c, 0);
}
++frequency[c];
}
return frequency;
}
public bool IsAnagram(string s1,string s2)
{
if (s1.Length != s2.Length)
return false;
var s1Array = s1.ToLower().ToCharArray();
var s2Array = s2.ToLower().ToCharArray();
Array.Sort(s1Array);
Array.Sort(s2Array);
s1 = new string(s1Array);
s2 = new string(s2Array);
return s1 == s2;
}
下面是一個沒有對兩個數組進行排序的算法。 假設 Dictionary 的 ContainsKey、Add、Remove 方法是 O(1),那么算法的時間復雜度是 O(N) 而不是使用 Sort 的 O(nlogn)。
static bool anagram(string s1, string s2)
{
if (s1.Length != s2.Length)
{
return false;
}
Dictionary<char, int> bucket = new Dictionary<char, int>(50);
for (int i = 0; i < s1.Length; i++)
{
if (s1[i] == s2[i]) continue;
for (int j = -1; j < 2; j = j + 2)
{
var aOrb = j == -1 ? s1[i] : s2[i];
if (bucket.ContainsKey(aOrb))
{
bucket[aOrb] += j;
if (bucket[aOrb] == 0)
{
bucket.Remove(aOrb);
}
}
else
{
bucket.Add(aOrb, j);
}
}
}
return bucket.Count == 0;
}
另一種方法是檢查第一個是否在第二個中包含字符。 然后從第一個字符中刪除該字符,直到沒有更多字符為止。
private bool IsAnagram(string a, string b)
{
if (a.Length != b.Length) return false;
List<char> list1 = a.ToList();
List<char> list2 = b.ToList();
for (int i = 0; i < a.Length; i++)
{
// try to remove list 1 item from list 2
// if didn't find any thing to remove. so they are not anagram
if (!list2.Remove(list1[i])) return false;
}
return true; // loop finished successfully. they are anagram
}
請注意, List<T>.Remove()
方法返回一個布爾值,指定該方法是否能夠刪除任何內容。
你可以在一行 Linq 中完成這一切。
List<char> list = "god".ToList();
bool isAnagram = "dog".All(ch => list.Remove(ch));
Linq 方法All<char>(Func<char,bool>)
將執行委托,直到Func<char,bool>
返回 false 或直到查詢結束。 如果 Func 返回 false 那么All
返回 false 。 否則它將返回true。
如果您的時間有限,這是一個更好/更有效的解決方案:
bool CheckAnagram(string str1, string str2)
{
if(str1.Length != str2.Length)
return false;
if(str1 == str2)
return true;
// based on 128 ASCII characeters.
// You can change the paramter depending on requirement
int charLength = 128;
int[] counter = new int[charLength];
for(int i=0; i<str1.Length; i++)
{
counter[str1[i]-'a']++;
counter[str2[i]-'a']--;
}
for (int c = 0; c < charLength; c++)
{
if(counter[c] != 0) return false;
}
return true;
}
private static void Main()
{
Console.WriteLine(IsAnagram(
"tom marvolo riddle",
"i am lord voldemort"));
}
public static bool IsAnagram(string word, string dest)
{
var w = WordSpliter(word);
var d = WordSpliter(dest);
return w.Count == d.Count && w.Count == w.Where(x => d.Contains(x)).ToList().Count;
}
public static List<(char Key, int Count)> WordSpliter(string word)
{
return word.Replace(" ", "").ToLower().GroupBy(c => c).Select(x => (
x.Key,
Count: x.Count()
)).ToList();
}
該解決方案在 codestandard.net 上被接受
public bool IsAnagram(string one, string two)
{
if(one.ToLower().Equals(two.ToLower()))
return true;
var array1 = one.ToCharArray();
var array2 = two.ToCharArray();
Array.Sort(array1);
Array.Sort(array2);
return array1 == array2;
}
使用一些LINQ,檢查是否字符串的連接中包含的任何char
,其中兩個字符串的次數不同。
或者,查看此SO問題及其答案或鏈接的非語言特定主題,以獲得更多的C#字謎檢查代碼。
using System;
using System.Linq;
public class Program
{
public void Main()
{
string str1 = "dog";
string str2 = "god";
bool isAnagram = (((str1 + str2).Any(c => str1.Count(x => x == c) != str2.Count(x => x == c))));
if (isAnagram)
{
Console.WriteLine("no anagram");
}
else
{
Console.WriteLine("Anagram");
}
}
}
此解決方案將檢查 anagram 恰好 1 次傳遞( O(Cn) where C = 1 )
public static bool IsAnagram(string s1, string s2) {
if (s1.Length != s2.Length)
return false;
int i = -1;
var chars = new Dictionary<char, int> ();
Func <char, int, int, int> updateCount = (c, side, pdiff) => {
int count = 0;
chars.TryGetValue (c, out count);
var newCount = count + side;
chars[c] = newCount;
if (count == 0)
return pdiff + 1;
else if (newCount == 0)
return pdiff - 1;
else
return pdiff;
};
int diff = 0;
foreach (var c1 in s1) {
i++;
var c2 = s2 [i];
if (c1 == c2)
continue;
diff = updateCount(c1, 1, diff);
diff = updateCount(c2, -1, diff);
}
return diff == 0;
}
public static void Main (string[] args)
{
string s1 = "asd";
string s2 = "ads";
Console.WriteLine (IsAnagram(s1, s2));
}
public bool IsAnagram(string firstString, string secondString)
{
List<char> firstlist = new List<char>();
firstlist.AddRange(firstString);
List<char> secondlist = new List<char>();
secondlist.AddRange(secondString);
if (secondlist.Count != firstlist.Count)
{
return false;
}
while (firstlist.Count != 0 && secondlist.Count != 0)
{
foreach (var sec in secondlist)
{
foreach (var fir in firstlist)
{
if (char.ToUpperInvariant(sec) == char.ToUpperInvariant(fir))
{
firstlist.Remove(fir);
break;
}
}
secondlist.Remove(sec);
break;
}
}
if (firstlist.Count == secondlist.Count)
return true;
return false;
}
嘗試這個
static bool isAnagrams(string str1,string st)
{
string str1 = "reaad";
string str2 = "Daaer";
char[] t = str1.ToCharArray();
var kt = t.Distinct();
string pattern = @"e";
// Create a Regex
Regex rg = new Regex(pattern);
Console.WriteLine(rg.Match(str1).Value);
foreach (var item in kt)
{
string pat = item.ToString();
Regex r = new Regex(pat,RegexOptions.IgnoreCase);
if (r.Matches(str1).Count != r.Matches(str2).Count)
{
return false;
}
}
return true;
}
char[] fArr = new char[First.Length];
char[] sArr = new char[Second.Length];
fArr = First.ToLower().ToCharArray();
sArr= Second.ToLower().ToCharArray();
if (fArr.Length == sArr.Length)
{
Array.Sort(fArr);
Array.Sort(sArr);
}
return new string(fArr) == new string(sArr) ? true : false;
我有一個字符串列表(不僅僅是兩個字符串)的解決方案。 如果您對它或任何其他感興趣,您可以使用它。
給定一個字符串數組,刪除作為先前字符串變位的每個字符串,然后按存儲順序返回剩余的數組。
private static List<string> GencoAnagrams(List<string> textList)
{
var listCount = textList.Count;
if (listCount == 1) return textList;
for (var j = 1; j < listCount; j++)
{
for (var i = 0; i < j; i++)
{
if (string.Concat(textList[j].OrderBy(x => x)).Equals(string.Concat(textList[i].OrderBy(y => y))))
{
textList.RemoveAt(j);
--listCount;
--j;
if (listCount == 1) break;
}
}
if (listCount == 1) break;
}
return textList;
}
我也感謝“ Thomas Krojer ”的回答,起初對我很有幫助。
if (String.Concat(a.OrderBy(c => c)).Equals(String.Concat(b.OrderBy(c => c))) ...
public static bool IsAnagram(this string a, string b)
{
//check the length are not same ? not Anagram
if (a.Length != b.Length)
return false;
// check both the strings are same ? Angram
if (a == b)
return true;
// Sort the characters alphabetically and compare them to one another.
return a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c));
}
class Anagrams
{
static void Main()
{
// 1
// Read and sort dictionary
var d = Read();
// 2
// Read in user input and show anagrams
string line;
while ((line = Console.ReadLine()) != null)
{
Show(d, line);
}
}
static Dictionary<string, string> Read()
{
var d = new Dictionary<string, string>();
// Read each line
using (StreamReader r = new StreamReader("enable1.txt"))
{
string line;
while ((line = r.ReadLine()) != null)
{
// Alphabetize the line for the key
// Then add to the value string
string a = Alphabetize(line);
string v;
if (d.TryGetValue(a, out v))
{
d[a] = v + "," + line;
}
else
{
d.Add(a, line);
}
}
}
return d;
}
static string Alphabetize(string s)
{
// Convert to char array, then sort and return
char[] a = s.ToCharArray();
Array.Sort(a);
return new string(a);
}
static void Show(Dictionary<string, string> d, string w)
{
// Write value for alphabetized word
string v;
if (d.TryGetValue(Alphabetize(w), out v))
{
Console.WriteLine(v);
}
else
{
Console.WriteLine("-");
}
}
}
這似乎比Linq版本快很多。
bool isAnagram = true;
string s1 = "ighfedcba";
string s2 = "higedcbaf";
char [] c1= s1.ToCharArray();
char [] c2= s2.ToCharArray();
Array.Sort(c1);
Array.Sort(c2);
for(int i = 0; i<c1.Length; i++)
{
if (c1[i] != c2[i]){
isAnagram = false;
break;
}
}
O(n) 解決方案
public bool Anagram(string s , string p)
{
char[] dS = s.ToCharArray();
char[] dP = p.ToCharArray();
Array.Sort(dS);
Array.Sort(dP);
string rS = new string(dS);
string rP = new string(dP);
return rS == rP;
}
string one = "aabba";
string two = "bbaaa";
int check = 0;
List<char> oneList = one.ToCharArray().ToList();
List<char> twoList = two.ToCharArray().ToList();
foreach (var letter in oneList /* the principal */)
{
if (twoList.Contains(letter))
{
check++;
}
}
if (check == twoList.Count)
{
return true;
}
else
{
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.