【问题标题】:How can check anagram strings in C#如何在 C# 中检查字谜字符串
【发布时间】:2015-12-23 01:02:45
【问题描述】:

给定两个字符串 A 和 B,检查它们是否是字谜。

如果一个字符串可以通过重新排列另一个字符串的字母来获得,则称两个字符串为字谜。

字谜的例子是

  • dog, god
  • abac, baac
  • 123, 312

abab, aabadab, baad 不是字谜。

输入:

输入的第一行是测试用例 T 的数量。 后面是T行,每行有两个空格分隔的字符串A和B;

输出

对于每个测试用例,如果它们是字谜,则打印“YES”,否则打印“NO”。 (不带引号)

约束

  1. 1
  2. A 和 B 都只包含小写拉丁字母 'a' 到 'z' 和 数字 0 到 9。
  3. 每个字符串A和B的长度不超过5*10^5 (500000)

`

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;
}

【问题讨论】:

标签: c# string


【解决方案1】:

这是你的解决方案吗?

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))) ...

【讨论】:

  • 简洁但效率不高? (打开日志?)
  • 不,这不是他的解决方案,他的解决方案更好。
  • 你可以做同样的事情甚至更短:var isAnagram = a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c));
  • 我没有检查 500k 字符串,因为我不相信这是真实的现场设置
  • 对于大字符串我会在周末测试一些东西
【解决方案2】:
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;
}

【讨论】:

    【解决方案3】:

    有快速的方法和简单的方法:

    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;
    }
    

    【讨论】:

      【解决方案4】:

      下面是一个不对两个数组进行排序的算法。假设 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;
          }
      

      【讨论】:

      • 为什么需要这条线bucket[aOrb] += j;
      • 这个想法是使用字典在两个字符串中查找不同的字符。在循环中,我们得到两个字符:一个来自 s1,另一个来自 s2。然后对于来自 s1 的字符,我们将 -1 添加到相应的字典条目,并为来自 s2 的字符添加 +1。如果结果为 0,则我们从字典中删除该条目。也可以不从字典中删除条目,但最后检查字典,使其没有任何非零条目。
      【解决方案5】:

      另一种方法是检查第一个是否在第二个中包含一个字符。然后从第一个字符中删除该字符,直到没有更多字符为止。

          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&lt;T&gt;.Remove() 方法返回一个布尔值,指定该方法是否能够删除任何内容。

      你可以在一行 Linq 中完成这一切。

      List<char> list = "god".ToList();
      
      bool isAnagram = "dog".All(ch => list.Remove(ch));
      

      Linq 方法 All&lt;char&gt;(Func&lt;char,bool&gt;) 将执行委托,直到 Func&lt;char,bool&gt; 返回 false 或查询结束。如果 Func 返回 false,则 All 也返回 false。否则返回true。

      【讨论】:

        【解决方案6】:

        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;
            }
        

        【讨论】:

          【解决方案7】:
              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();
              }
          

          【讨论】:

            【解决方案8】:

            如果您的时间有限,这是一个更好/有效的解决方案:

            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;
            }
            

            【讨论】:

              【解决方案9】:
                  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));
                  }
              

              【讨论】:

                【解决方案10】:

                此解决方案将检查 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));
                    }
                

                【讨论】:

                  【解决方案11】:

                  不区分大小写的可以试试这个:

                  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;          
                          }
                  

                  【讨论】:

                    【解决方案12】:

                    试试这个

                    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;
                    }
                    

                    【讨论】:

                      【解决方案13】:
                      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;
                      

                      【讨论】:

                      • 您应该在答案中添加更多上下文,而不是仅仅发布代码。
                      • 这与已有的provided answer 有何不同?
                      【解决方案14】:

                      我有一个字符串列表(不仅仅是两个字符串)的解决方案。 如果你对它或任何其他感兴趣,你可以使用它。

                      给定一个字符串数组,删除之前字符串的变位词的每个字符串,然后按存储顺序返回剩余的数组。

                      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))) ...

                      【讨论】:

                        【解决方案15】:

                        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;
                        
                        }
                        

                        【讨论】:

                        • 欢迎来到Stack Overflow。请查看How to Answer 部分。现在,你确定这个解决方案是 O(n) 吗?排序方法的复杂程度如何?
                        • 与已有的given 答案没有什么不同。
                        【解决方案16】:
                        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("-");
                                }
                            }
                        }
                        

                        【讨论】:

                          【解决方案17】:
                          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;
                                  }
                          

                          【讨论】:

                          • 虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。您可以使用edit 按钮改进此答案以获得更多选票和声誉!
                          猜你喜欢
                          • 2021-10-10
                          • 2021-12-12
                          • 2021-01-11
                          • 2013-08-18
                          • 2021-12-30
                          • 2016-04-07
                          • 2018-03-15
                          相关资源
                          最近更新 更多