python-3.x - 列表和字典:哪个更快
问题描述
我有以下代码通过交换元素对来对列表进行排序:
# Complete the minimumSwaps function below.
def minimumSwaps(arr):
counter = 0
val_2_indx = {val: arr.index(val) for val in arr}
for indx, x in enumerate(arr):
if x != indx+1:
arr[indx] = indx+1
s_indx = val_2_indx[indx+1]
arr[s_indx] = x
val_2_indx[indx+1] = indx
val_2_indx[x] = s_indx
counter += 1
return counter
def minimumSwaps(arr):
temp = [0] * (len(arr) + 1)
for pos, val in enumerate(arr):
temp[val] = pos
swaps = 0
for i in range(len(arr)):
if arr[i] != i+1:
swaps += 1
t = arr[i]
arr[i] = i+1
arr[temp[i+1]] = t
temp[t] = temp[i+1]
temp[i+1] = i
return swaps
第二个函数比第一个函数工作得快得多。但是,有人告诉我字典比列表快。这是什么原因?
解决方案
列表是一种数据结构,字典是一种数据结构。说一个比另一个“快”是没有意义的,就像你说一个苹果比一个橙子快一样。一个可能会长得更快,你可能会更快地吃掉另一个,当你放下它们时,它们可能会以相同的速度落到地上。不是水果更快,而是你用它做什么。
如果您的问题是您有一个字符串序列,并且您想知道给定字符串在序列中的位置,请考虑以下选项:
- 您可以将序列存储为列表。使用该方法查找给定字符串的位置
.index
需要线性搜索,在 O(n) 时间内遍历列表。 - 您可以将字典映射字符串存储到它们的位置。查找给定字符串的位置需要在 O(1) 时间内在字典中查找。
所以使用字典解决这个问题会更快。但还要注意,在您的第一个函数中,您正在使用列表的.index
方法构建字典 - 这意味着在 O(n) 时间内进行 n 次线性搜索,在 O(n^2) 时间内构建字典,因为您使用的是列表对于某些东西列表很慢。如果您在不进行线性搜索的情况下构建字典,则将花费 O(n) 时间:
val_2_indx = { val: i for i, val in enumerate(arr) }
但现在考虑一个不同的问题。你有一个数字序列,它们恰好是按某种顺序从 1 到 n 的数字。您希望能够在序列中查找数字的位置:
- 您可以将序列存储为列表。找到给定数字的位置需要在 O(n) 时间内再次进行线性搜索。
- 您可以像以前一样将它们存储在字典中,并在 O(1) 时间内进行查找。
- 您可以将逆序列存储在列表中,以便
lst[i]
保存原始序列中值的位置。i
这是有效的,因为每个排列都是可逆的。现在获得的位置i
是一个简单的列表访问,在 O(1) 时间内。
这是一个不同的问题,因此可能需要不同的时间来解决。在这种情况下,列表和字典都允许在 O(1) 时间内得到解决方案,但事实证明使用列表更有效。在字典中按键获取比在列表中按索引获取更长的常数时间,因为在字典中按键获取需要计算散列,然后探测数组以找到正确的索引。(从列表中获取只需要访问已知索引处的数组。)
第二个问题是您的第二个功能中的一个。请参阅此部分:
temp = [0] * (len(arr) + 1)
for pos, val in enumerate(arr):
temp[val] = pos
这将创建一个列表temp
,temp[val] = pos
无论何时arr[pos] == val
。这意味着列表temp
是 的逆排列arr
。在后面的代码中,temp
仅用于通过索引获取这些位置,这是一个 O(1) 操作,并且恰好比在字典中查找键更快。
推荐阅读
- android - 应用程序未在 Android 上运行
- entity-framework - Entity cannot load data from related class
- sql-server - T-SQL Self Join Table with External Table Grouping
- android - Kotlin,recyclerview 适配器如何通过 DESC 对查询结果进行排序
- arrays - How to map an array reference in Rust
- java - Java: How to rewrite using Lamda -- where an Exceptions can be thrown
- r - if (REML) p else 0L 中的错误:参数长度为零
- c# - C# 安装程序 ~ Windows 资源管理器中的文件版本与项目的不同
- arrays - 在 R 中,填充未知大小的向量的有效方法是什么?
- javascript - 使用 API 过滤和映射问题