Arrays 当myArray.reversed()的返回值分配给以前初始化的数组时,时间复杂度是否变为O(n)?抄写?
Apple docs表示.reversed()方法的时间复杂度为O(1) 在以下代码中,Arrays 当myArray.reversed()的返回值分配给以前初始化的数组时,时间复杂度是否变为O(n)?抄写?,arrays,swift,Arrays,Swift,Apple docs表示.reversed()方法的时间复杂度为O(1) 在以下代码中,arr(第2行)是ReversedCollection类型 为什么打印arr(第3行)不按相反顺序返回数字 // 1 - let a = [1, 2, 3, 4, 5] // 2 - let arr = a.reversed() // <- O(1) is the complexity of this operation. // 3 - print(arr) //
arr
(第2行)是ReversedCollection
类型
为什么打印arr
(第3行)不按相反顺序返回数字
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - let arr = a.reversed() // <- O(1) is the complexity of this operation.
// 3 - print(arr) // unexpected - prints ReversedCollection<Array<Int>>(_base: [1, 2, 3, 4, 5])
在下面的代码中,(第3行)a.reversed()
返回值为typeReversedCollection
,然后将其分配给arr
-typeArray
。我担心分配给arr操作会消除O(1)时间复杂性;它看起来类似于上面的代码(第2行)——我们将ReversedCollection
转换为数组
下面的代码与上面的代码相同吗
在下面代码中第3行的执行完成后,时间复杂度是否保持O(1)
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - var arr = a // arr is type Array<Int>
// 3 - arr = arr.reversed() // assigns a ReversedCollection<Array<Int>> to an Array
// 4 - print(type(of: arr) // prints Array<Int>
// 5 - print(arr) // print [5, 4, 3, 2, 1] as expected
关于下面的示例代码,(第3行)-这次我没有将arr.reversed()
分配给arr
。它导致arr
没有被反转,这不是我所期望的。我想避免在第3行中使用.reverse()
,因为它在O(n)中运行
//1-设a=[1,2,3,4,5]
//2-var arr=a//arr为数组类型
//3-arr.reversed()//不反转arr的项目
//5-print(arr)//prints[1,2,3,4,5]-不是我最初期望的
写时复制即使在反向集合
被分配/转换到数组
之后,是否仍保持时间复杂性O(1)?的结果是。反向()
只是在集合上反向迭代的结构。创建它需要一个固定的时间。与任何集合一样,对其进行迭代的成本为O(n)
所以let rev=a.reversed()
是O(1),但是let rev=Array(a.reversed())
是O(n),因为它在a
上进行迭代以生成副本。没有隐式转换Array
和ReversedCollection,它会将值复制到一个新数组中
Stdlib是开源的,所以你也可以看看。您将看到初始值设定项只是一个赋值:
internal init(_base: Base) {
self._base = _base
}
正如您所指出的,Array.reversed()是一个O(1)操作。它只是用逻辑包装原始数组,在访问索引时自动调整索引,以实现有效的反转
如果从反向集合显式创建新数组,则创建的是数据的完整副本,并且您将支付O(n)成本。我不认为斯威夫特的抄写优化在这里适用
下面是一个代码片段,您可以运行它来查看时间复杂性
var array = [Int]()
for i in 0..<1000000 {
array.append(i)
}
let startDate = Date()
let reversed = array.reversed() // O(1)
print(Date().timeIntervalSince(startDate)) // ~0s from start
var newArray = Array(reversed) // O(n)
print(Date().timeIntervalSince(startDate)) // ~0.2s from start
newArray[0] = 0
print(Date().timeIntervalSince(startDate)) // ~0.2s from start
var数组=[Int]()
对于0中的i.“苹果的文档显示了这种到数组的转换,在它的正下方,他们提到了O(1)。”您应该将我们链接到使这些索赔更新的文档。这只是一个误解。O(1)
仅适用于生成反向集合。将其复制到数组或字符串是线性时间。@Japsocket有“另一个场景在下面共享-(第3行)-返回错误-无法将rev分配给arr”然后显示//3-let arr=rev//Error-无法将“ReversedCollection”类型的值分配给“[Int]”类型。
这种情况不可能发生。数组是一种类型推断语言。您正在创建一个新对象,这将导致ReversedCollection
您的屏幕截图不是特别探索写时复制。多个数组
地址可以引用同一个下划线数组缓冲
(这是CoW正在优化的内容,而不是数组
)。不管怎么说,这里没有牛,但即使有,您的测试用例也不会告诉我们。如果使用了写时复制,这将是一个重要因素。我做了几个测试来检查,但可能没有彻底检查。问题已更新,以反映发生的情况。关于@RobNapier?书面复制在这里不相关。如果你能解释是什么原因让你认为它是相关的,我可以讨论为什么它不是,但我无法想象为什么你认为它是相关的。ReversedCollection是不可变的(它不符合MutableCollection),所以我不知道您在想什么“写”。以一种非常宏观的方式,CoW系统允许self.\u base=\u base
为O(1),从技术上讲,这在Swift中不是免费的。但在我看来,这真是吹毛求疵。
// 1 - let a = [1, 2, 3, 4, 5]
// 2 - var arr = a // arr is type Array<Int>
// 3 - arr.reversed() // does not reverse arr's items
// 5 - print(arr) // prints [1, 2, 3, 4, 5] - not what I initially expected
internal init(_base: Base) {
self._base = _base
}
var array = [Int]()
for i in 0..<1000000 {
array.append(i)
}
let startDate = Date()
let reversed = array.reversed() // O(1)
print(Date().timeIntervalSince(startDate)) // ~0s from start
var newArray = Array(reversed) // O(n)
print(Date().timeIntervalSince(startDate)) // ~0.2s from start
newArray[0] = 0
print(Date().timeIntervalSince(startDate)) // ~0.2s from start