Arrays 当myArray.reversed()的返回值分配给以前初始化的数组时,时间复杂度是否变为O(n)?抄写?

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) //

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)               // unexpected - prints ReversedCollection<Array<Int>>(_base: [1, 2, 3, 4, 5])

在下面的代码中,(第3行)
a.reversed()
返回值为type
ReversedCollection
,然后将其分配给
arr
-type
Array
。我担心分配给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