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
答案 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
之后,您需要扣除不符合第二个条件的可能排列数,可以从列表A
和B
我认为计算列表A
和B
中排除的排列的数量比处理从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