我有一个家庭作业问题,我只能在O(max(F)*N)
(N
约为10^5
且F
为10^9
)复杂性时解决这个问题,我希望你可以帮帮我我获得了N
套4个integer
个数字(名为S, F, a
和b
);每组4个数字以这种方式描述一组数字:第一个连续数字,从S
开始包含在集合中。接下来的b
个连续数字不是,然后是下一个a
数字,重复此数字直到达到上限F
。例如,对于S=5;F=50;a=1;b=19
,该集合包含(5,25,45); S=1;F=10;a=2;b=1
,该集合包含(1,2,4,5,7,8,10);
我需要找到包含在奇数个集合中的整数。保证对于给定的测试,只有1个数字符合这一条件。
我试图通过min(S)
和max(F)
之间的每个数字来检查这个数字包含多少套数,如果它包含在奇数个数组中,那么这是答案。正如我所说,通过这种方式,我得到一个O (F*N)
太多了,我不知道怎么能看到一个数字是否在奇数集中。
如果你能帮助我,我会非常感激。提前谢谢你,对不起我的英语和解释感到抱歉!
答案 0 :(得分:3)
我很想使用二分法。
选择一个值x,然后计算所有集合中存在的数字< = x。
如果这是奇数,那么答案是< = x,否则> x。
这应该花费时间O(Nlog(F))
假设我们有设置
[S=1,F=8,a=2,b=1]->(1,2,4,5,7,8)
[S=1,F=7,a=1,b=0]->(1,2,3,4,5,6,7)
[S=6,F=8,a=1,b=1]->(6,8)
然后我们可以表:
N(y)= y包含在集合中的次数,
C(z)= sum(范围(1,z)中y的N(y))%2
y N(y) C(z)
1 2 0
2 2 0
3 1 1
4 2 1
5 2 1
6 2 1
7 2 1
8 2 1
然后我们使用二分法找到C(z)变为1的第一个位置。
答案 1 :(得分:1)
似乎有必要在这些集合上找到一种方法来执行集合操作,特别是交集,而无需生成实际集合。如果你能做到这一点,测试中所有这些集合的交集应该只留下一个数字。将a
和b
部分放在一边,很容易看出你如何取两个包含S和F之间所有整数的集合的交集:交集只是S = max的集合( S1,S2)和F = min(F1,F2)。
这给你一个起点;现在你必须弄清楚如何创建考虑a
和b
的两组交集。
答案 2 :(得分:1)
从每个连续集中获取数字,并使用结果集的内容对它们进行异或。即,如果该号码当前标记为“存在”,则将其更改为“不存在”,反之亦然。
最后,您将在结果集中标记一个数字,这个数字将出现奇数次。所有其他人都会进行多次异或,所以他们将恢复原状。
至于复杂性,你只需要处理每个输入项一次,所以它基本上是输入项总数的线性 - 至少假设你对结果集的操作是恒定的复杂性。至少如果我理解他们是如何措辞的话,那似乎符合要求。
答案 3 :(得分:0)
听起来S被认为是非负面的。鉴于您对O(max(F)*N)
时间边界的渴望,您可以使用类似筛分的方法。
有一个整数数组,每个候选数字都有一个条目(即min(S)和max(F)之间的每个数字)。遍历所有四元组,并将1添加到与每个四元组所代表的数字相关的所有数组位置。最后,查看数组以查看哪个计数是奇数。它代表的数字是满足您条件的数字。
这是有效的,因为你将进入N个四倍,并且每个都需要O(最大(F))或更少的时间(假设S总是非负的)来计算包含的数字。这给你O(最大(F)* N)。