查找满足这两个条件的子集数量?

时间:2020-01-15 10:36:18

标签: python arrays algorithm

def findNumber(N,A,B):
    return count

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 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)

我尝试了这段代码,但是我不知道如何迭代a和b的所有值而不会使它变得很慢。在n> 10 ^ 2上已经变慢了。

1 <= n <= 10 ^ 5 1 <= len(A)<= 10 ^ 6

2 个答案:

答案 0 :(得分:0)

我对您的代码做了一些小的修改, 这段代码真的很慢,因为它遍历了可以由10 ^ 5个项目组成的整个列表,并且执行了一些嵌套操作,这会使复杂度飙升至10 ^ 10,这确实很慢

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  

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

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

中找出

我认为计算列表AB中排除的排列的数量比处理从1到N的所有排列要有效得多。

答案 1 :(得分:0)

我对如何在不生成子集的情况下解决此问题感兴趣,例如,我发现连续的子集总数为n(n + 1)/ 2,我只是想知道如何知道要排除的子集数量。 / p>

这给了我一个主意-实际上,计算单个对(A [i],B [i])排除的子集数量非常简单。由于要排除的子集可能会重叠,因此要对多对进行比较更具挑战性,因此仅为每对减去一个数字将不起作用。起作用的是拥有一组所有N(N + 1)/ 2个子集的数字或索引,并从中删除排除的子集的索引;最后,减少索引集的基数是剩余子集的所需数量。

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
相关问题