我正在尝试通过解决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
}
}
答案 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
是您的解决方案,findMaxConsecutiveOnes2
是Joakim's,而findMaxConsecutiveOnes3
是此答案中提出的解决方案。
在终端中使用优化(-O
)进行编译,以下是执行时间:
49.079 us
54.016 us
14.883 us
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个元素的数组上。
但是,在较小的阵列上,它被证明是最快的解决方案。
这是最快的:
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
)数组,我都没有注意到执行时间有任何改善。