一种解决方案是使用双向映射每个键到一个整数,以允许通过使用 random.randrange(0,N) 从双向映射到键的整数范围中进行选择来随机选择一个键,其中N 是键的数量。
添加一个新键只是为其分配下一个更高的整数。删除键会将该键的 int 重新分配给在删除键值对之前分配给先前最高 int 的键。为了清楚起见,提供了 Python 代码。
Python 代码:
def create(D): # O(len(D))
# Create the bidirectional maps from the dictionary, D
keys = D.keys()
ints = range(len(keys)
int_to_key = dict(zip(keys, ints))
key_to_int = dict(zip(ints, keys))
return (int_to_key, key_to_int)
def add(D, int_to_key, key_to_int, key, value): # O(1)
# Add key-value pair (no extra work needed for simply changing the value)
new_int = len(D)
D[key] = value
int_to_key[new_int] = key
key_to_int[key] = new_int
def remove(D, int_to_key, key_to_int, key): # O(1)
# Update the bidirectional maps then remove the key-value pair
# Get the two ints and keys.
key_int = key_to_int[key]
swap_int = len(D) - 1 # Should be the highest int
swap_key = int_to_key[swap_int]
# Update the bidirectional maps so that key now has the highest int
key_to_int[key], key_to_int[swap_key] = swap_int, key_int
int_to_key[key_int], int_to_key[swap_int] = swap_key, key
# Remove elements from dictionaries
D.remove(key)
key_to_int.remove(key)
int_to_key.remove(key)
def random_key(D, int_to_key): # O(1)
# Select a random key from the dictionary using the int_to_key map
return int_to_key[random.randrange(0, len(D))]
def remove_random(D, int_to_key, key_to_int): # O(1)
# Randomly remove a key from the dictionary via the bidirectional maps
key = random_key(D, int_to_key)
remove(D, int_to_key, key_to_int, key)
注意:在 D 中添加/删除键而不使用上述适当的函数会破坏双向映射。这意味着最好将其作为一个类来实现。