我们定义x1,x2,...,x_n为点(数字)的序列,[s_i,t_i]为1≤i≤n的n个段的集合。如果s_i≤x_j≤t_i,则点x_j在线段i内。我想找到积分最高的细分。
现在要解决这个问题,我想我们可以根据s对x和间隔进行排序。保留一个单独的数组T,使T [i] =段i中的最大点。将此数组中的所有值初始化为0。然后,对于每个x,检查所有符合约束的间隔,并相应地增加T [i]。
在最坏的情况下,这可能需要O(n ^ 2)。但是我觉得我在这里有很多多余之处。如何提高效率?
答案 0 :(得分:2)
请澄清一下,如果问题是一维的,则X
(x_1
至x_n
)中的点是数字,而线段是间隔。
您可以通过对X
进行排序并使用结果索引来轻松解决此问题。通过找到两个相应的索引[s, t]
和i
,可以有效地计算段j
中的点数。查找(使用二进制搜索或最有效的方法)i
,使x_i < s <= x_(i+1)
,和j
,使x_j <= t < x_(j+1)
。注意不等式(如果s
或t
可能在X
中)。 [s, t]
中的点数等于j-i
。
如果s < x_1
或t > x_n
是可能的,只需在X
的两端附加一个点(最小和最大)。
这具有O(n log n)
的复杂度,受排序算法限制。如果您可以使用诸如计数排序之类的方法来将值用作数组的索引(或将键作为多集的索引),那么您可以通过做更多的工作来改进它。
让S
为包含所有段s
的每个t
和每个[s, t]
的点集。这个想法是为X
构建索引数组(有点像用于计数排序)。
首先,以A
和A[x in X] = 1
的形式构建数组A[x not in X] = 0
。然后,再次遍历以构建数组A_less
,以使A_less[i]
等于所有A[j]
与j < i
的和。
例如,如果A = [1, 0, 0, 1, 0, 1, 0]
,则A_less = [0, 1, 1, 1, 2, 2, 3]
。您可以使用一个简单的计数器来构建此数组。
您现在可以直接引用此数组以获取值小于或等于另一个的点数。在前面的示例中,X
中显然有三个点,其值分别为0、3和5。通过引用A_less
,您可以知道存在A_less[4] = 2
个点的值较小等于或等于4。
类似地,构建A_less_equal
使得A_less_equal[i]
等于所有A[j]
与j <= i
的总和。使用相同的示例A_less_equal = [1, 1, 1, 2, 2, 3, 3]
。
现在,对于任何段[s, t]
,您都可以通过计算A_less_equal[t] - A_less[s]
获得其包含的点数。所有这些都具有复杂性O(n)
。
如果您的点不是整数(至少不容易用作索引),那么您仍然可以使用相同的想法,将数组替换为排序集,其键是X
中的每个值或S
(您需要在S
中添加值才能在末尾查找它们。)