【问题标题】:Pairing duplicate elements in an array将数组中的重复元素配对
【发布时间】:2021-11-02 12:09:10
【问题描述】:

我正在尝试将数组的重复元素配对并计数。

当给定数组是:[10, 20, 20, 10, 10, 30, 50, 10, 20] 时,我期望 numberOfPairs 为 3。因为有 2 对 10 和 1 对 20。

我的“if 条件”正在检查当前元素的索引是否是第一个索引。如果不是最后一个索引,则表示当前元素存在重复。所以我给 numberOfPairs 加 1。

对于输入 [10, 20, 20, 10, 10, 30, 50, 10, 20],我的 numberOfPairs 是 2 但应该是 3。 对于输入 [1 1 3 1 2 1 3 3 3 3],myNumberOfPairs 根本不打印?但它应该是 4。

我在这里错过了什么?

func sockMerchant(n: Int, ar: [Int]) -> Int {
    // Write your code here
    var array = ar
    var numberOfPairs = 0
    
    for i in 0..<array.count {
       var element = array[i]
       let indexOfLastElement = array.lastIndex(of: element)
       let indexOfFirstElement = array.firstIndex(of: element)
       print("indexOfLastElement is \(indexOfLastElement)")
       print("indexOfFirstElement is \(indexOfFirstElement)")
       
       if indexOfFirstElement != indexOfLastElement {
           numberOfPairs += 1
           array.remove(at: indexOfFirstElement!)
           array.remove(at: indexOfLastElement!)
           continue
       }
       return numberOfPairs
    }
     return numberOfPairs
 }

【问题讨论】:

  • 这很简单:从一个简单的例子开始,然后调试你的程序。单步执行代码,检查变量。程序在什么时候没有像您想象的那样运行?

标签: ios arrays swift xcode loops


【解决方案1】:

您在访问remove(at:) 的同时调用remove(at:) 来改变您的array,这就是为什么您会出现这些奇怪的副作用。

我假设您正在尝试解决 Leetcode 任务(或类似任务),因此我不会预先提供解决方案。我对您的建议是考虑一种算法,该算法在您阅读同一列表的这些内容时不涉及更改列表的内容。

【讨论】:

    【解决方案2】:

    所以,感谢@Vym 和@Martin R,我已经解决了以下问题。

    func sockMerchant(n: Int, ar: [Int]) -> Int {
    // Write your code here
    var array = ar
    var numberOfPairs = 0
    var newArray = [Int]()
    var done = false
    
    for i in 0..<array.count {
       let element = array[i]
       let indexOfLastElement = array.lastIndex(of: element)
       let indexOfFirstElement = array.firstIndex(of: element)
       
       if indexOfFirstElement != indexOfLastElement {
           newArray.append(element)
           numberOfPairs = newArray.count/2
           done = true
       }
       
    }
    if done == true {
        return numberOfPairs
    }
     return numberOfPairs
    

    }

    【讨论】:

    • 很高兴您能找到可行的解决方案。附言我个人并没有指责你作弊。请避免下次使用全部大写,并记住这是一个问答网站,不鼓励“基于意见”的答案。
    • 别担心! downvote 是 downvote - 不要强调它。你不必解释自己。
    • 谢谢维姆。我真的很感激。这里很新,习惯了。
    【解决方案3】:

    我同意@MartinR 的观点,在这种情况下,您应该放置断点并逐行遍历您的代码,很高兴您自己发现了错误。

    但在性能方面,lastIndexfirstIndex 是非常繁重的操作,因为它们可能会考虑所有项目而一无所获,这使得 Big O notation 的算法在 O(log n) 左右。在这种情况下,字典被广泛使用(如果您对空间没有太多限制)。

    您可以将 value 用作 key 并将其作为 value 用于字典并计算所有项目,然后像这样求和:

    func sockMerchant(ar: [Int]) -> Int {
        ar.reduce(into: [Int:Int]()) { map, value in
            map[value, default: 0] += 1
        }.reduce(0) { sum, count in
            sum + count.value / 2
        }
     }
    

    【讨论】:

    • 这不会返回正确的结果。请使用问题中的示例或简单的测试用例进行测试,[1,1,1,1]
    • @JoakimDanielson 谢谢,我有点误解了这个问题,更新的答案应该可以工作
    • Swift 是一种类型推断语言reduce(into: [:]) { $0[$1, default: 0] += 1 }.reduce(0) { $0 + $1.value/2 }
    • @LeoDabus 当然可以。但我认为命名参数大大提高了可读性;当计算非常简单时,我只使用速记。字典类型也是如此:我希望作者更清楚这里发生了什么。 swift 在显示错误和在代码中使用[:] 提供建议方面可能非常糟糕。
    • map[value, default :0] += 1 实际上是做什么的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 2014-05-26
    • 2021-02-11
    • 2018-07-02
    相关资源
    最近更新 更多