【发布时间】:2017-07-05 01:24:26
【问题描述】:
我目前正在学习一个在线算法课程,其中老师不提供解决算法的代码,而是提供粗略的伪代码。因此,在上网寻找答案之前,我决定自己尝试一下。
在这种情况下,我们正在研究的算法是归并排序算法。在获得伪代码后,我们还深入分析了针对数组中 n 个项目的运行时间算法。经过快速分析,老师到达6nlog(base2)(n) + 6n作为算法的大致运行时间。
给出的伪代码仅用于算法的合并部分,如下所示:
C = output [length = n]
A = 1st sorted array [n/2]
B = 2nd sorted array [n/2]
i = 1
j = 1
for k = 1 to n
if A(i) < B(j)
C(k) = A(i)
i++
else [B(j) < A(i)]
C(k) = B(j)
j++
end
end
他基本上以4n+2(2 用于声明i 和j,4 用于执行的操作数量——for,if ,数组位置分配和迭代)。我相信为了课堂,他将其简化为6n。
这一切对我来说都很有意义,我的问题来自我正在执行的实现以及它如何影响算法以及它可能增加的一些权衡/低效率。
以下是我使用游乐场快速编写的代码:
func mergeSort<T:Comparable>(_ array:[T]) -> [T] {
guard array.count > 1 else { return array }
let lowerHalfArray = array[0..<array.count / 2]
let upperHalfArray = array[array.count / 2..<array.count]
let lowerSortedArray = mergeSort(array: Array(lowerHalfArray))
let upperSortedArray = mergeSort(array: Array(upperHalfArray))
return merge(lhs:lowerSortedArray, rhs:upperSortedArray)
}
func merge<T:Comparable>(lhs:[T], rhs:[T]) -> [T] {
guard lhs.count > 0 else { return rhs }
guard rhs.count > 0 else { return lhs }
var i = 0
var j = 0
var mergedArray = [T]()
let loopCount = (lhs.count + rhs.count)
for _ in 0..<loopCount {
if j == rhs.count || (i < lhs.count && lhs[i] < rhs[j]) {
mergedArray.append(lhs[i])
i += 1
} else {
mergedArray.append(rhs[j])
j += 1
}
}
return mergedArray
}
let values = [5,4,8,7,6,3,1,2,9]
let sortedValues = mergeSort(values)
我的问题如下:
在
merge<T:Comparable>函数开头的guard语句实际上是否使其效率更低?考虑到我们总是将数组减半,它唯一成立的时间是基本情况以及数组中有奇数个项目时。
在我看来,这实际上会增加更多的处理并提供最小的回报,因为它发生的时间是我们将数组减半到没有项目的程度。关于我在合并中的
if语句。由于它检查多个条件,这会影响我编写的算法的整体效率吗?如果是这样,对我的影响似乎会因它何时会突破if语句而有所不同(例如,在第一个条件或第二个条件下)。
这是在分析算法时需要重点考虑的事情吗?如果是的话,当它从算法中爆发出来时,你如何解释方差?
您可以就我所写的内容提供任何其他分析/提示,我们将不胜感激。
【问题讨论】:
-
我想知道 for 循环中的 6n 部分是否认为 A[i] 或 B[j] 在合并期间被读取了两次,一次在 if 期间,一次在移动期间。
标签: swift algorithm sorting mergesort