簡體   English   中英

如何在 C# 中檢查 anagram 字符串

[英]How can check anagram strings in C#

給定兩個字符串 A 和 B,檢查它們是否是字謎。

如果可以通過重新排列另一個字符串的字母來獲得一個字符串,則稱兩個字符串是字謎。

字謎的例子是

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

abab, aabadab, baad不是字謎。

輸入 :

輸入的第一行是測試用例的數量T。后面是T行,每行有兩個空格分隔的字符串A和B;

輸出

對於每個測試用例,如果它們是字謎,則打印“YES”,否則打印“NO”。 (不帶引號)

約束

  1. 1 <= T <= 10
  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;
}

這是您的解決方案嗎?

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 ,其中兩個字符串的次數不同。

.NET提琴

或者,查看此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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM