【问题标题】:Find the missing element in a given permutation查找给定排列中的缺失元素
【发布时间】:2018-04-20 03:40:01
【问题描述】:

首先,有一点背景:

我正在研究the Codility lessons 之一,尽管这很容易解决,但从逻辑上讲,它并不容易解决,就性能而言。

我已经能够将其归结为:

public func solution(_ A : inout [Int]) -> Int {
    let B = A   // Assigning it to a local speeds it up.
    return Array<Int>(Set(B)).sorted(by: {$0<$1}).reduce(0) { ($1 == $0 + 1) ? $1 : $0 } + 1
}

但是,这只是 WEE 有点太慢了。我想主要原因是 reduce 会遍历数组的所有元素,即使答案可能很早。我可能无法加快速度。

但我想试试。我正在看的部分是这样的:

.reduce(0) { ($1 == $0 + 1) ? $1 : $0 }

我想知道我是否可以使这种比较更有效。

我必须检查 $1 是否等于 $0 + 1。我无法避免这种比较。

三元运算符实际上并不比 if 子句快,但它看起来更酷;)。

有没有比基本的“==”运算符性能更高的方法来比较两个正整数的等价性?

顺便说一句:这不是“为我做作业”的问题。这是相当合法的,这些 Codility 课程不会给你任何荣誉或任何东西。他们只是一个有趣的练习。我想知道如何做到这一点,因为我确信我将来会需要它。

【问题讨论】:

  • 也许我误读了这个问题,但您不能将数组中的所有数字相加,然后从 1 到 n + 1 的总和中减去它以获得缺失的数字吗?
  • 嗯...我会试试的。我喜欢 Codility 的原因之一是他们有一些非常偷偷摸摸的单元测试。它可能会打破他们奇怪的极端案例之一。
  • 你不能使用 A.sorted(by..... - Codility 说你应该假设列表是不同的。所以没有理由首先创建一个集合。
  • @LittleGreenViper 试试看,如果它失败了,请告诉我,我很好奇
  • 问题不在于比较太慢,而是您使用了错误的算法,特别是对数字进行排序使其变慢。 – 这是一个众所周知的编程任务,只需 google “查找丢失的数字”,例如这里:geeksforgeeks.org/find-the-missing-number

标签: arrays swift compare reduce


【解决方案1】:

使用另一个概念在 python 中的 100% 得分:

def solution(A):
 Index=0;
 while (Index<len(A)):
  while((A[Index]-1) != Index and A[Index]<=len(A)):
   Tmp=A[Index]; #Permut
   A[Index]=A[Tmp-1];
   A[Tmp-1]=Tmp;
  Index+=1;
 Index=0;
 while Index<len(A):
  if((A[Index]-1) != Index) :
   return Index+1;
  else:
   Index+=1;
 return len(A)+1;  
pass

背后的想法是,对于给定的排列,每个元素 A[Index]-1 应该与 Index 匹配,但缺少的元素除外。然后排列数组的元素,直到当 A[Index]>len(A) 时达到或未达到对应关系。

【讨论】:

    【解决方案2】:

    使用 cmets 中 @TNguyen 建议的解决方案,下面的代码在正确性和性能上都达到了 100%。

    您只需要通过调用Array(1...A.count+1) 生成正确的数组,其中包含[1..(N + 1)] 范围内的每个整数。然后使用reduce(0,+) 对其元素求和,最后减去输入数组A 的元素之和。两个和之间的差给出了缺失的元素。

    public func solution(_ A : inout [Int]) -> Int {
        return Array(1...A.count+1).reduce(0,+)-A.reduce(0,+)
    }
    

    更快的解决方案是使用数学公式1+2+...+n=n(n-1)/2 进行第一次求和。

    public func solution(_ A : inout [Int]) -> Int {
        return (A.count+1)*(A.count+2)/2-A.reduce(0,+)
    }
    

    【讨论】:

    • 这是不正确的,你不需要像这样对 1..n+1 求和。有公式! 1+ 2+ ... + n = n(n+1) / 2,
    • @TNguyen 这不是错误的。它可能不是最理想的,但绝对不是不正确的,因为结果与 n*(n-1) 相同。但是,更新了我的答案以反映更快的解决方案。
    • 鉴于他试图以最快的方式做到这一点,我会说这是不正确的。我也推翻了我的反对意见。
    • 这对我的几个单元测试很不利。我将不得不审查它们,看看我是否公平......感谢您的意见。这是我喜欢这个网站的原因之一。它帮助我从不同的方向看待事物。
    • @LittleGreenViper 这个解决方案实际上通过了所有测试,查看我提交的解决方案和结果here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多