Algorithm 在多个表中查找偶数个条目
给定一个数字Algorithm 在多个表中查找偶数个条目,algorithm,lookup,Algorithm,Lookup,给定一个数字N和一组由唯一元素组成的表,如何找到在每个表中只出现偶数次的所有N个条目集 注意:实际上我有几百个表,每个表包含大约一百万个条目,其中每个条目都是介于0到200万之间的数字。我试图找到大约500个数字的集合。 这就是为什么我在寻找一个有效的算法 例如,给定N=4和下表: Table #1 #2 #3 #4 #5 ,---. ,---. ,---. ,---. ,----.
N
和一组由唯一元素组成的表,如何找到在每个表中只出现偶数次的所有N个条目集
注意:实际上我有几百个表,每个表包含大约一百万个条目,其中每个条目都是介于0到200万之间的数字。我试图找到大约500个数字的集合。这就是为什么我在寻找一个有效的算法 例如,给定
N=4
和下表:
Table #1 #2 #3 #4 #5
,---. ,---. ,---. ,---. ,----.
| 0 | | 5 | | 7 | | 4 | | 9 |
| 1 | | 3 | | 6 | | 1 | | 7 |
| 9 | | 2 | | 4 | | 0 | | 11 |
| 2 | | 7 | | 3 | | 7 | | 10 |
| 8 | | 6 | | 9 | | 5 | | 2 |
| 5 | | 0 | | 0 | | 8 | | 12 |
'---' '---' '---' '---' '----'
要找到的解决方案是:
Solution table #1 #2 #3 #4 #5
-------- ------------------------------------------------
0, 2, 4, 10 : [0, 2] [0, 2] [0, 4] [0, 4] [2, 10]
0, 1, 2, 9 : [0, 1, 2, 9] [0, 2] [0, 9] [0, 1] [9, 2]
0, 2, 4, 11 : [0, 2] [0, 2] [0, 4] [0, 4] [2, 11]
0, 2, 4, 12 : [0, 2] [0, 2] [0, 4] [0, 4] [2, 12]
0, 2, 8, 9 : [0, 8, 2, 9] [0, 2] [0, 9] [0, 8] [9, 2]
1, 3, 6, 8 : [8, 1] [3, 6] [3, 6] [8, 1] []
1, 4, 9, 10 : [1, 9] [] [9, 4] [1, 4] [9, 10]
1, 4, 9, 11 : [1, 9] [] [9, 4] [1, 4] [9, 11]
1, 4, 9, 12 : [1, 9] [] [9, 4] [1, 4] [9, 12]
1, 8, 10, 11: [8, 1] [] [] [8, 1] [10, 11]
1, 8, 10, 12: [8, 1] [] [] [8, 1] [10, 12]
1, 8, 11, 12: [8, 1] [] [] [8, 1] [11, 12]
2, 3, 5, 7 : [2, 5] [2, 3, 5, 7] [3, 7] [5, 7] [2, 7]
2, 5, 6, 7 : [2, 5] [2, 5, 6, 7] [6, 7] [5, 7] [2, 7]
3, 6, 10, 11: [] [3, 6] [3, 6] [] [10, 11]
3, 6, 10, 12: [] [3, 6] [3, 6] [] [10, 12]
3, 6, 11, 12: [] [3, 6] [3, 6] [] [11, 12]
4, 8, 9, 10 : [8, 9] [] [9, 4] [8, 4] [9, 10]
4, 8, 9, 11 : [8, 9] [] [9, 4] [8, 4] [9, 11]
4, 8, 9, 12 : [8, 9] [] [9, 4] [8, 4] [9, 12]
我使用过这个python程序,但它是一个幼稚的实现,我不喜欢它的复杂性,它比:
X = (
(0,1,9,2,8,5),
(5,3,2,7,6,0),
(7,6,4,3,9,0),
(4,1,0,7,5,8),
(9,7,11,10,2,12)
)
# find unique elements across all lists
ALL = tuple(set([l for i in range(len(X)) for l in X[i]]))
LEN = len(ALL)
def find_all():
Solutions = []
for i in range(0, LEN-3):
for j in range(i+1, LEN-2):
for k in range(j+1, LEN-1):
for l in range(k+1, LEN):
if count_even((ALL[i], ALL[j], ALL[k], ALL[l])):
Solutions.append([ALL[i], ALL[j], ALL[k], ALL[l]])
return Solutions
def count_even(values):
"""return True if some elements of `values` appear
an even number of times in every list"""
for List in X:
Accumulator = 0
for Value in values:
for Elem in List:
if Elem == Value:
Accumulator += 1
if Accumulator & 1 == 1:
return False
return True
for v in find_all():
print v
我在优化中遇到的函数是find_all()
,因为它有太多嵌套循环。也许可以使用高斯消去法或树,或任何其他众所周知的算法 非常感谢您的帮助。(抱歉,无法发表评论) 作为一个小的改进,您可以预计算并存储(例如,在hashmap中,或者如果值是从0到已知I_MAX的整数,则在数组中)每个表中每个元素的出现次数(时间O(n*n)) 然后:
- 构建N个元素的所有集合O(N^N)
- 对于每个表,对于每个表:
对于集合中的每个元素: 在表中查找发生的事件,并将其添加到表的总数中。如果得到奇数结果,则拒绝该集
也许有一种完全不同的更智能的算法,它不会生成所有包含N个元素的集合,但在任何情况下,都可能出现问题有O(N^N)个答案的情况,因此,在最坏的情况下,你无法做得更好。(如果与N相比,N被认为是常数)。如果没有太多的表,这一方法效果很好。如果大于31,则必须将位向量的格式从int更改为更复杂的格式 评论解释了它是如何工作的
N=4
TABLES = [
[0,1,9,2,8,5],
[5,3,2,7,6,0],
[7,6,4,3,9,0],
[4,1,0,7,5,8],
[9,7,11,10,2,12]
]
#Make a bit mask for each item, with a bit for each table
#The table's bit is 1 if the number occurs an even number
#of times in the table
#A set of N items is then valid iff the masks for those items
#XOR to 0
MASKS={}
bit=1
for table in TABLES:
for val in table:
MASKS[val] = MASKS.get(val,0) ^ bit
bit*=2
ITEMS=sorted(MASKS.keys())
#Make REACHABLE[n][val] = the highest position pos such that
#you can make XOR value val using n elements at positions >= pos
REACHABLE=[]
for n in range(0,N):
REACHABLE.append({})
REACHABLE[0][0]=len(ITEMS)
for pos in range(len(ITEMS)-1,-1,-1):
itemval=MASKS[ITEMS[pos]]
for n in range(N-1,1,-1):
for testkey in REACHABLE[n-1].keys():
newval=itemval^testkey
REACHABLE[n][newval]=REACHABLE[n].get(newval,pos)
REACHABLE[1][itemval]=REACHABLE[1].get(itemval,pos)
#now print all the solutions using the REACHABLE array to ensure that we
#don't go down any non-viable paths
def printSolutions(prefix, needval, startpos, count):
if count<1:
if needval==0:
print(prefix)
return
for pos in range(startpos,len(ITEMS)):
testval=needval^MASKS[ITEMS[pos]]
if REACHABLE[count-1].get(testval,-1) > pos:
prefix.append(ITEMS[pos])
printSolutions(prefix,testval,pos+1,count-1)
prefix.pop()
printSolutions([],0,0,N)
您描述的算法相当于:1)生成偶数次出现的所有元素的列表;2) 从该列表生成N个项目的所有组合。(1) 应该需要O(n)时间。(2) 所需时间与输出大小成比例。@MattTimmermans,在第二种解决方案中,“2”和“9”出现的次数为奇数。为了清晰起见,我添加了一个python程序,第5列。此外,列表是由独特的元素组成,这可能会有所帮助。哦,你需要每个表包含一个偶数目的项目,从每一组N。。。这使这成为一个有趣的问题。最大表数和最大N是多少?我刚刚在帖子中回答了。数以百计的表包含数百万个条目,我正在尝试创建大约500个基数的集合。我喜欢这个想法,但不幸的是,我有大约200个表,每个表包含大约100万个条目。数字在0到200万之间。这将使200个表x 100万个条目x 200万位整数=50 TB的快速存储和大量RAM。我在原来的帖子上加了一条注释。谢谢啊,那太糟糕了。从最大独立集问题到这个问题,每个边映射到一个小表格,每个顶点映射到一个元素。这意味着您的问题是NP难问题,在最坏的情况下,您找到的所有算法的表数都是指数级的。由于分支修剪,printSolutions从不进行不会打印解决方案的递归调用,因此它是O(min(n^n,n*numberofof of of of of of of of of of the the the the the solutions))。如果您有n^(n-1)个解决方案,那么您还有其他问题。当然,你的问题中有n^n个解,所以如果必须把它们全部打印出来,当然没有算法比O(n^n)更好。
[0, 1, 2, 9]
[0, 2, 4, 10]
[0, 2, 4, 11]
[0, 2, 4, 12]
[0, 2, 8, 9]
[1, 3, 6, 8]
[1, 4, 9, 10]
[1, 4, 9, 11]
[1, 4, 9, 12]
[1, 8, 10, 11]
[1, 8, 10, 12]
[1, 8, 11, 12]
[2, 3, 5, 7]
[2, 5, 6, 7]
[3, 6, 10, 11]
[3, 6, 10, 12]
[3, 6, 11, 12]
[4, 8, 9, 10]
[4, 8, 9, 11]
[4, 8, 9, 12]