我想通过强力(O(N ^ 3)或递归bactracking)找到“唯一”三角形的最大数量(每个数组元素只能使用一次)。应该采取什么方法?
答案 0 :(得分:1)
首先假设所有边的长度都是正整数。 (对于实数,间隔是半开 - 半 - 关闭并使其更加混乱。)
基本上,如果我们找到一种有效的方法来获取每个[a,b]
范围0<=a<=b
范围内长度的边数,我们可以将其处理为:
edgeList = sort edgeList by length ascending order
foreach ( edge1 in edgeList )
foreach ( edge2 in edgeList where [edge2 >= edge1] )
answer = answer + count_edge_number ( edge2 , edge1+edge2-1 );
return answer;
因此我们只需要这样的方式。要做到这一点,您只需按长度按升序对边进行排序,使用二进制搜索来查询相关区间的下限和上限的索引(订阅)。 (也就是说,对于任何[a,b]
,使用二进制搜索来查找i
最大element[i]<a
,最小j
element[j]<=b
)。这适用于O(logN)
。
因此,您的任务可以在O(N^2LogN)
中实现,远远优于草书O(N^3)
。
答案 1 :(得分:0)
创建一个地图(hashmap应该没问题),端点映射到side。所以每一方都有2个条目 - 每个端点一个。现在,您可以从任何给定的终点开始有效地查找所有方面。
一些基本的伪代码:
// map[X] is all unused sides with X as end-point
// markAsUsed should also remove the side from the map
// markAsUnused should also add the side to the map
// initial function call for any unused side
backTrackFunction(anyUnusedSide)
backTrackFunction(side AB)
if map.isEmpty
Found a solution.
markAsUsed(AB)
for each side AC in map[A]
if map[C].contains(CB)
// AB, CB and AC form a triangle
markAsUsed(CB)
markAsUsed(AC)
backTrackFunction(anyUnusedSide)
// Backtrack
markAsUnused(CB)
markAsUnused(AC)
以上可能存在一些问题,但它只是一个起点。