【问题标题】:change a range of items in a dictionary in order O(n)以 O(n) 的顺序更改字典中的一系列项目
【发布时间】:2013-03-06 03:32:49
【问题描述】:

我正在尝试在 O(n) 的运行时更改字典中的一系列值。 其中 n 是我需要更改的范围内的元素数。

例如,如果我的字典中有键的数字,并且我正在获取键范围的列表 列表 = [ (key1,key3), (key2,key3)] 在这种情况下,如果我从 d = {key1: odd , key2: even, key3: odd , key4: even} 所以我会有 在第一个范围之后 d = {key1: even , key2: odd, key3: even , key4: even} 在第二个键范围之后 d = {key1: even , key2: even, key3: odd , key4: even}

可以用python实现吗?

【问题讨论】:

  • n 是什么?字典中的元素数量?范围的长度?需要更改的元素数量?
  • 好评更新了我的帖子
  • 键的顺序是任意的,因此不清楚如何使用数字范围选择要更改的键。你有另一个变量存储键的顺序吗?
  • dicts 是无序的,所以你不能索引它们。
  • 我的键是从 0 到无穷大的数字

标签: python


【解决方案1】:

你可以这样做。这是 O(n),其中 n 是您需要更改的键数。

change_keys = (1,2)
for key in change_keys:
    d[key] = 'odd' if d[key]=='even' else 'even'

如果你有一个无元组的范围列表,例如:

key_ranges = [(2,6), (4,8)]
key_ranges = [ range(a[0],a[1]) for a in key_ranges ]

我相信你可以使用:

change_keys = set.union(*map(set,key_ranges))

但是,当然,生成集合需要操作。但是在某些时候,您要么必须复制密钥,要么找到重复项。不确定是否可以避免。

或者如果你想重复,千万不要打电话给set

key_ranges = [(2,6), (4,8)]
change_keys = []
for a in key_ranges:
    change_keys.extend(range(a[0],a[1])

【讨论】:

  • @Quantico:为什么你认为这不是 O(n)?您基本上每个键都在执行一项操作。
  • 这仍然不会改变您对每个键执行一次操作的事实,并且(希望)不会重复您范围内的任何键,它将是 O(n)。即使使用嵌套的 for 循环,操作的总数也类似于 sum(len(eachrange) for eachrange in list_of_tuples)
  • @Quantico:当您似乎不知道那是什么时,人们很难给您想要的答案。您最近的评论似乎与您之前要求使用 O(n) 算法的请求完全矛盾,即使存在重叠范围。
  • @elfonso 是对的,如果您希望有很多重叠范围,您实际上可以通过计算 change_keys 列表中的每个键并丢弃任何显示为偶数的键来节省计算 (?)次数。但是,您仍然没有保存键的数量。
  • 这里是 OP 的提示:首先按第一个元素对范围列表进行排序。 @askewchan 如果 n 是列表中的范围数,则计算 change_keys 中的每个键所需的时间呈指数增长。 OP:您可能应该考虑数据结构的设计。如果您需要翻转范围 (0,10000000),如果您使用的是 dict,那么相对于输入中的位数而言,这将花费指数级的时间。
【解决方案2】:

如果 n 的真正含义是范围列表的长度,则无法使用字典来实现。例如,如果范围是 [(0,100000000000)],那么在字典中执行此操作将相对于范围列表中的位数呈指数增长。

如果您选择了正确的数据表示和算法,您可以在 nlogn 中实现您的操作,其中 n 是范围列表的长度。就范围内的实际元素数量而言,这通常比 O(n) 的运行时间快得多。

这是一个可能的解决方案:

  1. 定义一个由范围列表组成的数据结构。列表中某个范围内的元素已从其原始起始状态“翻转”。

  2. 定义一个例程,将一组新的翻转(传入范围列表)与现有翻转“合并”,并找到不相交的翻转集。

例程应该:

  1. 将数据结构的范围与传入的范围列表合并。
  2. 找到第一个元素最小的范围集,称之为 A。
  3. 查找在 A 中最后一个范围结束之前开始的范围集,将其与 A 合并。
  4. 根据第一个元素对 A 中的范围进行排序。
  5. 对于 A 中的每个 (b1,?),将 A 中的每个范围 (a,b) 拆分为 (a,b1) 和 (b1,b)。A 中的范围现在应该是不重叠的。
  6. 删除所有 (a,b) 对。 (a,b) 现在在 A 中应该是唯一的。
  7. 将所有范围 (a,b)、(b,c) 连接到 A 中的 (a,c) 中。
  8. 将 A 添加到数据结构中。转到第 2 步,从尚未添加的下一个最小元素开始。

【讨论】:

  • 我仍在考虑您建议的解决方案。一旦我有更好的理解,我会告诉你或接受答案:)
  • 这是一个学校项目。正如您在我最初的询问中看到的那样,我并没有要求解决方案,只是想知道 python 是否可以在 O(n) 中执行某个操作。
  • 嗯,答案是肯定的,如果“n 是我需要更改的范围内的元素数”。但我怀疑这就是你的项目的意思,因为那毫无意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 2013-02-25
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
相关资源
最近更新 更多