设计一种采用O(n log n)确定的分而治之算法

时间:2015-09-07 22:54:30

标签: algorithm divide-and-conquer

我获得了一组球,我的最终目标是找到至少一半的球是否是相同的颜色。我每次只能挑两个球并确定它们是否是相同的颜色。那么如何设计一种需要O(n log n)确定才能解决这个问题的分治算法呢?如果有人对这个问题有任何想法,那么非常感谢你!

4 个答案:

答案 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   .  .  .  .  .  .  .  .  .  .  =

因此,比较两个相等的对比比较一个相等和不同的对更有效,而这反过来比比较两个不同的对更有效。

因此,最佳算法类似于:

  • 比较两个球:AB,CD,EF ......,将球分成相等和不同的球。
  • 然后通过比较每对中的一个球,将相等的对彼此进行比较,可能导致彼此不同的较大的相等组。
  • 然后将不同的对与这些较大的相等组进行比较,从大到小。
  • 继续这样做,直到其中一半球在一组中,或者没有足够的单球留下与最大组的关系仍然未知。

你必须弄清楚这种方法的细节;我可以看到几种选择,但没有明显的最佳选择。基本规则应该始终是:首先将对,四重奏,八位字节......与最大数量的相等球进行比较。