Python 找到满足这两个条件的子集的数目?
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上 我试着尽可能地解释,如果需要的话,请要求澄清 编辑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上 我试着尽可
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