快速连续的最大数量

时间:2018-12-21 16:35:28

标签: swift algorithm data-structures

我正在尝试通过解决LeetCode上的简单面试问题来学习Swift。

问题如下:

给出一个二进制数组,找到该数组中最大连续1个数。

示例1:

输入:[1,1,0,1,1,1]

输出: 3

说明:前两位或后三位是连续的1。     连续1的最大数量为3。

注意:

输入数组将仅包含0和1。 输入数组的长度为正整数,不超过10,000

我已经解决了以下问题,没问题,它可以运行并涵盖了测试用例,但是它表明我的提交仅比所有提交快73%。我想知道是否有更好的方法来解决这个问题。我的解决方案时间复杂度为O(n)。

class Solution {
    func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {

        var globalMax = 0
        var localMax = 0

        for num in nums
        {
           if num == 1
           {
              localMax += 1
              globalMax = max(globalMax, localMax)
           }
           else
           {
                localMax = 0
           }  
        }
        return globalMax
    }
}

3 个答案:

答案 0 :(得分:2)

进行两次较小的调整,实际上并不需要检查数组大小,仅在找到0且结尾时才需要调用max

func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {
    var globalMax = 0
    var localMax = 0

    for num in nums {
       if num == 1 {
          localMax += 1              
       } else {
            globalMax = max(globalMax, localMax)
            localMax = 0
       }  
    }
    return max(globalMax, localMax)
}

我用split和reduce进行了一次实验,该组合似乎比上面的组合要快一些,但与评论中链接的组合大致相同

func findMaxConsecutiveOnes3(_ nums: [Int]) -> Int {
    return nums.split(separator: 0).reduce(ArraySlice<Int>(), { ($1.count > $0.count) ?  $1 : $0 }).count
}

答案 1 :(得分:1)

也许他们期望一些Swift特技。

如果没有-我可以假设检查系统在每1个项目中都不喜欢计算。

仅在1-0转换(或在数组末尾)的情况下,才可以计算全局最大值。在这种情况下,您还需要记住0-1变化时的索引1。

答案 2 :(得分:1)

您的问题更适合Code Review site。 LeetCode中的排名不可靠,并且可能从提交到下一个(使用相同的代码)有所不同。

这里是一种避免使用if .. else(原始Java代码here)的解决方案:

func findMaxConsecutiveOnes4(_ nums: [Int]) -> Int {
    var globalMax = 0
    var localMax = 0

    for num in nums {
        localMax *= num
        localMax += num
        globalMax = max(globalMax, localMax)
    }
    return globalMax
}

为了进行基准测试,我使用了以下代码:

let array = (0...10_000).map { _ in Int.random(in: 0..<2) }

let start1 = mach_absolute_time()
let x1 = findMaxConsecutiveOnes1(array)
let end1 = mach_absolute_time()
print("1st", x1, Double(end1 - start1)/Double(1e3), "us")

let start2 = mach_absolute_time()
let x2 = findMaxConsecutiveOnes2(array)
let end2 = mach_absolute_time()
print("2nd", x2, Double(end2 - start2)/Double(1e3), "us")

let start3 = mach_absolute_time()
let x3 = findMaxConsecutiveOnes3(array)
let end3 = mach_absolute_time()
print("3rd", x3, Double(end3 - start3)/Double(1e3), "us")

findMaxConsecutiveOnes是您的解决方案,findMaxConsecutiveOnes2Joakim's,而findMaxConsecutiveOnes3是此答案中提出的解决方案。

在终端中使用优化(-O)进行编译,以下是执行时间:

  • findMaxConsecutiveOnes1:49.079 us
  • findMaxConsecutiveOnes2:54.016 us
  • findMaxConsecutiveOnes3:14.883 us

少于Swift在线提交的100.00%(暂时)

312

LeetCode将以下实现视为当前最快的实现:

func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {

    guard !nums.isEmpty else {
        return 0
    }

    var globalMax = 0
    var localMax = -1

    for i in 0..<nums.count {
        if nums[i] != 1 { //It is faster than: if nums[i] == 0
            localMax = i
        }
        globalMax = max(globalMax, i - localMax)
    }
    return globalMax
}

Here是原始的C ++实现。

在我的基准测试中,它没有达到预期的效果: 33.615 us 在10,000个元素的数组上。

但是,在较小的阵列上,它被证明是最快的解决方案


更快的解决方案

308

这是最快的:

func findMaxConsecutiveOnes(_ nums: [Int]) -> Int {

    guard !nums.isEmpty else {
        return 0
    }

    var globalMax = 0
    var lastZeroIdx = -1

    for i in 0..<nums.count {
        if nums[i] == 0 {
            globalMax = max(lastZeroIdx == -1 ? i : i - lastZeroIdx - 1, globalMax)
            lastZeroIdx = i
        }
    }
    globalMax = max(lastZeroIdx == -1 ? nums.count : nums.count - lastZeroIdx - 1, globalMax)
    return globalMax
}

它是从this Java实现中移植的。

在我的基准测试中,无论是小的(10个元素)数组还是大的(10,000个元素-> 42.363 us)数组,我都没有注意到执行时间有任何改善。