【问题标题】:Find First Unique Number查找第一个唯一编号
【发布时间】:2014-07-07 06:09:16
【问题描述】:

我最近参加了一项 Codility 测试,问题是找到数字序列中的第一个唯一数字。虽然我使用 LINQ 得到了正确的结果,但它显然在计算上过于昂贵且不够可扩展。

我将如何改进我的解决方案?

var a = new int[] {1, 2, -3, 4, 5, -6, 0, 8, 9, 1, 2};
const int expected = -3;            
var retVal = -1;
var y = a.GroupBy(z => z).Where(z => z.Count() == 1).Select(z => z.Key).ToList();
if (y.Count > 0) retVal = y[0];

Console.Write(retVal==expected);

【问题讨论】:

标签: c# unique


【解决方案1】:

这个怎么样:

var result = a.ToLookup(i => i).First(i => i.Count() == 1).Key;

这应该是-3。

它构建了一个Lookup 对象,其中包含使用列表中的每个数字创建的键和相同数字的值。

在重复的情况下,会在每个键下创建多个条目。第一个唯一值将是Lookup 中具有一个条目的第一个组。

(您可以轻松地使用GroupBy,而不是ToLookup。最终结果将是相同的。)

【讨论】:

  • 你能解释一下吗?
  • 我不认为ToLookup 在这里有很大的不同,但是在外部结果上不调用ToListCount 有很大的改进。
【解决方案2】:

试试这个

    var result = a.GroupBy(g => g).Where(w => w.Count() == 1).Select(s => s.Key).FirstOrDefault();

【讨论】:

  • 如果没有包含 1 个元素的组,则会抛出 NullReferenceException
  • @ad1Dima 我知道你是对的 - 只是一个例子 - iv 编辑了我的代码
【解决方案3】:

我决定测试上面发布的各种答案,并使用 StopWatch 类计算滴答数。

将 y.Count > 0 更改为 y.Any() 导致第二低的滴答计数,但根据 Baldrick 的评论,最大的减少属于该组

为了获得每个测试运行 50 次的平均值。

 Ticks
   Min   Max     Avg  Actual
    2  14502     584  -3     Original
    2    919      40  -3     if (y.Any()) actual = y[0];
    2   1423      60  -3     a.GroupBy(g => g).Where(w => w.Count() == 1)
                                            .Select(s => s.Key)
                                            .FirstOrDefault();
    2   1553      65  -3     a.ToLookup(i => i).First(i => i.Count() == 1).Key;
    2    317      15  -3     a.GroupBy(i => i).First(i => i.Count() == 1).Key;

【讨论】:

    猜你喜欢
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2021-10-10
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多