【问题标题】:对于给定的单词,计算可能的字谜的数量
【发布时间】:2022-01-23 16:19:57
【问题描述】:

对于给定的单词,计算可能的字谜的数量。 结果词不必存在于字典中。 字谜不必重复,也不必生成字谜,只需计算它们的数量。

最后一个测试不工作,我不知道我应该如何让它工作。你能帮帮我吗?

这是我的代码:

    using System;

    static void Main(string[] args)
    {
        string word = Console.ReadLine();
        int wordLenth = word.Length;
        int sameLetter = 1;

        for (int i=0;i<wordLenth;i++)
        {
            for (int j=i+1;j<wordLenth;j++)
            {
                if (word[i]==word[j])
                {
                    sameLetter++;
                }
            }
        }
        int firstResult=1, secondResult=1, lastResult;
        for (int i=1; i <= wordLenth; i++)
        {
            firstResult *= i;
        }
        for (int i = 1; i <= sameLetter; i++)
        {
            secondResult *= i;
        }
        lastResult = firstResult / secondResult;
        Console.WriteLine(lastResult);     
    }

Results:

Compilation successfully executed.
Test 1: Correctly calculate the number of anagrams for "abc" - successful
Test 2: Correctly calculate the number of anagrams for "abc" - success
Test 3: Correctly calculates the number of anagrams for "aaab" - failed
Expected results: "4"
Results obtained: "1"

如果有重复的字母,提交的解决方案不会正确计算唯一字谜的数量。

【问题讨论】:

  • 您的解决方案行不通,因为您只检查了一次sameLetter,但是如果您有两个或多个重复的字母怎么办,例如“aaabbbcccdddd”?
  • 你也可以用一些数学来解决这个问题,例如math.stackexchange.com/questions/114654/…

标签: c# arrays string algorithm anagram


【解决方案1】:

如果您有长度为 nm 不同字母 w1, ..., wm 的单词,其中 wiith 字母的出现, 可能的字谜的数量是

数学:

N = n! / w1! / w2! / ... / wm!

例如:

  1. 对于abc,我们有n = 3m = 3w1 = w2 = w3 = 1
N = 3! / 1! / 1! / 1! = 6 / 1 / 1 / 1 = 6
  1. 对于aaab,我们有n = 4m = 2w1 = 3, w2 = 1
N = 4! / 3! / 1! = 24 / 6 / 1 = 4

代码:

using System.Linq;
using System.Numerics;

...

private static BigInteger Factorial(int value) {
  BigInteger result = 1;

  for (int i = 2; i <= value; ++i)
    result *= i;

  return result;
}

private static BigInteger CountAnagrams(string value) {
  if (string.IsNullOrEmpty(value))
    return 1;

  return value
    .GroupBy(c => c)
    .Aggregate(Factorial(value.Length), (s, group) => s / Factorial(group.Count()));
}

演示: (Fiddle)

  string[] tests = new string[] {
    "a",
    "aaa",
    "abc",
    "aaab",
    "abracadabra",
    "stackoverflow",
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,20} => {CountAnagrams(test)}"));

  Console.Write(report);

结果:

                   a => 1
                 aaa => 1
                 abc => 6
                aaab => 4
         abracadabra => 83160
       stackoverflow => 3113510400

编辑:如果您不允许使用System.NumericsSystem.Linq,您可以尝试使用long

    private static long Factorial(int value)
    {
        long result = 1;

        for (int i = 2; i <= value; ++i)
            result *= i;

        return result;
    }

    private static long CountAnagrams(string value)
    {
        if (string.IsNullOrEmpty(value))
            return 1L;
        
        Dictionary<char, int> groups = new Dictionary<char, int>();

        foreach (var c in value)
            if (groups.TryGetValue(c, out int v))
                groups[c] += 1;
            else
                groups.Add(c, 1);
        
        long result = Factorial(value.Length);
        
        foreach (int v in groups.Values)
            result /= Factorial(v);
        
        return result;
    }

【讨论】:

  • 我复制了你的代码,但如果我写: aaa => 6 ; aaac =>12
  • @Laurențiu Cozma:我已经在答案 (dotnetfiddle.net/Xx0Zkq) 中提供了 fiddle,请您运行它吗?它返回 12 而不是 4?
  • @Laurențiu Cozma:好吧,提供您的代码(例如,通过 .net fiddle),我会更正它
  • @Laurențiu Cozma:似乎给你评分的网站不允许你使用 Linq,我提供了一个(简化的?)没有 Linq。没有 BigInteger 解决方案:请参阅我的编辑
  • @Laurențiu Cozma:尝试添加using System.Collections.Generic; 或使用System.Collections.Generic.Dictionary&lt;char, int&gt; groups = new System.Collections.Generic.Dictionary&lt;char, int&gt;(); 而不是Dictionary&lt;char, int&gt; groups = new Dictionary&lt;char, int&gt;();
猜你喜欢
  • 2021-10-16
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 2013-03-21
  • 2014-12-24
  • 1970-01-01
  • 2015-05-06
相关资源
最近更新 更多