Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在多个表中查找偶数个条目_Algorithm_Lookup - Fatal编程技术网

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)

  • 对于每个表,对于每个表:
    对于集合中的每个元素: 在表中查找发生的事件,并将其添加到表的总数中。如果得到奇数结果,则拒绝该集

这需要时间O(n*n)+O(n^n)+O(n^n*T*n),这是(对于T=n/2):O(n^3*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]