我获得了一组球,我的最终目标是找到至少一半的球是否是相同的颜色。我每次只能挑两个球并确定它们是否是相同的颜色。那么如何设计一种需要O(n log n)确定才能解决这个问题的分治算法呢?如果有人对这个问题有任何想法,那么非常感谢你!
答案 0 :(得分:1)
也许你可以倒退 - 如果你不知道n(log n)
比较中的答案,那么不到一半的球是相同的颜色。对它们进行合并排序分组......
r g r b r y r r // worst case arrangement
rg rb ry rr
↓ // 3 * (n / 4) comparisons
rr gb rrr y
↓ // 3 * (n / 8) comparisons
rrrrr gby
答案 1 :(得分:0)
我假设您可以对颜色进行排序(例如,您可以将颜色的哈希值计算为可以排序的整数;我无法想到任何无法进行哈希处理的数据类型)。然后,您可以在O(n log n)
时间内按颜色对球进行简单排序,然后在已排序的集合中扫描一次,并确定连续相同颜色的球的运行。你的答案是,最大运行中的球数是否>球数。
修改强>
问题实际上是O(n)。对于n个球,使用具有O(1)插入的哈希表。无论何时已经存在,都要增加哈希表组中元素的计数,并跟踪其他地方的最大组计数。
每当最大计数达到n / 2时,您甚至可以提前退出,这应该是随机集上平均运行时间的一半。
<强> EDIT2 强>
O(n ^ 2)
的示例性证明的草图我坚信,只允许进行相等比较时,没有O(n log n)解决方案。看下面的例子,它应该产生真实,正好有一半As,其余的都是不同的:
第一次划分
n = 16
AAAAAAABCDEFGHIA
AAAAAAAB CDEFGHIA
AAAA AAAB CDEF GHIA
AA AA AA AB CD EF GH IA
现在征服了。我们需要在每个征服步骤中找到所有组,因为每个组都可能与另一个大组合并,因此它是所有组中的大多数。
在这个例子中,左半边的A显然是赢家,但我们在右半边需要一个额外的A.由于右半部分在分而治之设置中不知道左半部分,因此右侧也会尝试在最终合并之前找到最大的组,以n / 2组大小为1结束。
在下面的表示法中,我使用字母前面的数字表示该大小的已找到组。
2A 2A 2A 1A1B 1C1D 1E1F 1G1H 1I1A 1+1+1+1 +1+1+1+1 =4+4 =8
4A 3A1B 1C1D1E1F 1G1H1I1A 1*1+2*1 +2*2+2*2 =3+8 =11
7A1B 1C1D1E1F1G1H1I1A 1*2 +4*4 =2+16=18
8A1B1C1D1E1F1G1H1I 2*8 =16
53
n log2 n = 16*4=64
在右侧,我注意到合并组所需的比较次数。要将具有x组的集合和具有y组的集合合并,需要进行O(x y)比较,当两个集合是不相关时(即将一组中的每一组与另一组中的每一组进行比较)。 在这个例子中需要53个比较,它低于64的n log2 n。 左侧的比较表现得非常线性。如果你分析你得到的模式(对于n> 7)
Log2(n)-2+ Sum{i=0..Log2(n)}(2^i) = n/2 - 3 + Log2(n)
但等等,在正确的比较数量上有一个平方项。我们来研究一下。每行(最后一次合并除外)使前一行加倍,并以(n / 4)^ 2比较结束。这给了
Sum{i=0..Log2(n)-2}( (n/4)^2 (1/2)^i ) = 1/8 (n^2 - 2*n)
事实上,通过这种分而治之的方法,我们最坏情况下的比较数是O(n ^ 2),这似乎是合乎逻辑的。如果所有条目都不同,并且我们每次只能测试两个是否相等,我们需要对每个条目进行测试,以找出是否真的没有对。
不知道我是否遗漏了什么东西,但是当我只允许使用comarisons时,问题似乎是在O(n log n)中无法解决的问题。
答案 2 :(得分:0)
我们可以将您的问题减少到以下。
如果给定组中的球按颜色分组,您希望找到最大组是否至少是该组大小的一半。
这更容易递归地解决。 (此问题未针对空集定义,请单独处理。)
class Group { // with appropriate constructors
int size;
Color color;
}
Group findLargestGroupWithSameColors(Set<Ball> ballSet) {
if (ballSet.size() > 1) {
// Divide set into two (preferably equal) sets.
Group first = recursive call on first half.
Group second = recursive call on second half.
if (first.color.equals(second.color)) {
return new Group(first.color, first.size + second.size);
} else {
if (first.size > second.size) {
return first;
} else {
return second;
}
}
} else {
return single element's color and size = 1
}
}
祝你好运
答案 3 :(得分:0)
每个球(相同或不同)之间的比较可以在这样的图表中显示:
A B C D E F G H I J K L
A
B =
C . .
D . . !
E . . . .
F . . . . !
G . . . . . .
H . . . . . . =
I . . . . . . . .
J . . . . . . . . !
K . . . . . . . . . .
L . . . . . . . . . . =
=
含义相等,!
含义不同,.
含义尚未检查。
此示例中显示的情况是12个球;在这种情况下,有66个比较。当然,您不需要进行66次比较来填写图表;如果A = B且B = C,则可以推导出A = C.此外,您只需填写图表的一部分即可知道半球是否具有相同的颜色。问题是,哪种比较顺序可以快速提供最多的信息。
如果两对相等,如图中的AB和GH,则比较每对中的一对,例如A和G也会告诉你AH,BG和BH是否相等:
A B C D E F G H I J K L
A
B =
C . .
D . . !
E . . . .
F . . . . !
G = = . . . .
H = = . . . . =
I . . . . . . . .
J . . . . . . . . !
K . . . . . . . . . .
L . . . . . . . . . . =
将来自相同对的球与来自不同对的球(如AC(A = B,C!= D))进行比较,将告诉您AD,BC和BD是否相等,但仅在A = C时;否则AD和BD仍然是未知的。
A B C D E F G H I J K L
A
B =
C ! !
D ? ? !
E . . . .
F . . . . !
G . . . . . .
H . . . . . . =
I . . . . . . . .
J . . . . . . . . !
K . . . . . . . . . .
L . . . . . . . . . . =
比较来自两个不同对的球,如CE(C!= D,E!= F),如果C = E,则不会告诉你DF,如果C!=不会告诉你CF,DE或DF E.
A B C D E F G H I J K L
A
B =
C . .
D . . !
E . . ! ?
F . . ? ? !
G . . . . . .
H . . . . . . =
I . . . . . . . .
J . . . . . . . . !
K . . . . . . . . . .
L . . . . . . . . . . =
因此,比较两个相等的对比比较一个相等和不同的对更有效,而这反过来比比较两个不同的对更有效。
因此,最佳算法类似于:
你必须弄清楚这种方法的细节;我可以看到几种选择,但没有明显的最佳选择。基本规则应该始终是:首先将对,四重奏,八位字节......与最大数量的相等球进行比较。