Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.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
Python 找到满足这两个条件的子集的数目?_Python_Arrays_Algorithm - Fatal编程技术网

Python 找到满足这两个条件的子集的数目?

Python 找到满足这两个条件的子集的数目?,python,arrays,algorithm,Python,Arrays,Algorithm,Count是满足以下条件的数组-[1,2,3,…,N]子集的总数: 1。所有子集都应该是连续的。 2。任何子集都不应包含A[i]和B[i](顺序无关紧要)。 范例 N=3,A=[2,1,3],B=[3,3,1] 所有子集=[1]、[2]、[3]、[1,2]、[2,3]、[1,2,3] 无效子集=[2,3],因为A[0]和B[0]在其中。[1,2,3]因为它包含A[1],B[1]和A[2],B[2] 所以数到4 我能够计算出连续子集的总数将是N(N+1)/2,但我被困在如何满足条件2上 我试着尽可

Count是满足以下条件的数组-[1,2,3,…,N]子集的总数:

1。所有子集都应该是连续的。

2。任何子集都不应包含A[i]和B[i](顺序无关紧要)。

范例

N=3,A=[2,1,3],B=[3,3,1]

所有子集=[1]、[2]、[3]、[1,2]、[2,3]、[1,2,3]

无效子集=[2,3],因为A[0]和B[0]在其中。[1,2,3]因为它包含A[1],B[1]和A[2],B[2]

所以数到4

我能够计算出连续子集的总数将是N(N+1)/2,但我被困在如何满足条件2上

我试着尽可能地解释,如果需要的话,请要求澄清

编辑

def findNumber(N,A,B):
    return count
我尝试了这段代码,但我不知道如何迭代a和b的所有值而不使其变得非常缓慢。它已经在n>10^2时减速了


1我对你的代码做了一些小修改, 这段代码非常慢,因为它在整个列表上进行迭代,可以由10^5个项目组成,并执行一些嵌套操作,这将使复杂性猛增到10^10,这非常慢

def findallvalid(n,a,b):
    for w in range(1, n+1):
        for i in range(n-w+1):
            if not((a[0],b[0]) in (i+1,i+w+1)):
                yield range(i+1,i+w+1)

我最接近的假设,因为代码只需要返回项目的计数 它可以用数学方法求解

N个大小列表的所有传染性排列都是
(N*(N+1))/2+1
之后,您需要扣除不符合第二个条件的可能排列的计数,这可以从列表
A
B

我认为从列表
A
B
中计算排除排列的计数要比从1到N的所有排列有效得多

我感兴趣的是如何在不生成子集的情况下处理这个问题,例如,我发现总的连续子集将是n(n+1)/2,我只是想知道如何知道要排除的子集数

这给了我一个想法——事实上,计算一对(a[i],B[i])排除的子集的数量非常简单。更具挑战性的是对多个对执行此操作,因为排除的子集可能重叠,因此仅为每个对减去一个数字是不可行的。有效的方法是拥有所有N(N+1)/2子集的一组数字或索引,并从中删除排除子集的索引;最后,缩减索引集的基数是剩余子集的所需数量

from collections import defaultdict

def findallvalid(N,A,B):
  a_in = defaultdict(list)
  b_in = defaultdict(list)

  for idx, a in enumerate(A):
    a_in[a].append(idx)
  for idx, b in enumerate(B):
    b_in[b].append(idx)

  def diff_elem_index(subset):
    indecies = []
    for elem in subset:
      indecies.extend(a_in[elem])
      indecies.extend(b_in[elem])
    return len(set(indecies)) == len(indecies)

  for set_window in range(1, N+1):
      for start_idx in range(N - set_window + 1):
        sett = list(range(start_idx+1,start_idx + set_window + 1))
        if diff_elem_index(sett):
          yield sett  
def findNumber(N、A、B):
计数=N*(N+1)//2
powerset=set(范围(计数))#可能间隔的枚举集
对于拉链中的a、b(a、b):
如果a>b:a,b=b,a#设a为较低的数字
#当a和b在子集中时,它们构成长度“span”的子集
span=(b-a)+1
start=0#当前长度w的invervals开始的索引
对于范围(1,N+1)内的w:#对于所有间隔长度w

如果span请用您已有的代码更新问题。当您说“不应包含
A[i]
B[i]
”时,您的意思是只有
A[i]
B[i]
在子集中时,子集才是invlid吗,对于相同的
i
?@00是,这是唯一的条件,但子集是连续的。@CosminStaicu我在问题中添加了我的代码。A和B的最大或典型长度是多少?我尝试了您的解决方案,并对其进行了修改,因此它只返回计数。但还是超过了10秒的时间限制。可以解释如何找到要排除的集合数。
def findNumber(N, A, B):
    count = N*(N+1)//2
    powerset = set(range(count))    # set of enumeration of possible intervals
    for a, b in zip(A, B):
        if a > b: a, b = b, a       # let a be the lower number
        # when a and b are in a subset, they form a sub-subset of length "span"
        span = (b-a)+1
        start = 0       # index where the invervals of current length w begin
        for w in range(1, N+1):     # for all interval lengths w
            if span <= w:           # if a and b can be in interval of length w
                first = 0 if b <= w else b-w    # index of first containment
                last = a                        # index of last containment
                # remove the intervals containing a and b from the enumeration
                powerset -= set(range(start+first, start+last))
            start += N+1-w          # compute start index of next length w
    return len(powerset)            # number of remaining intervals