给定一组3个数字的集合,找到最大的不相交集。例如,设C = {(3,4,5),(4,5,6),(1,2,3),(6,9,10),(7,8,9)}。此输入应返回3,因为最大不相交集是{(1,2,3),(4,5,6),(7,8,9)}。如何编写一个程序来输出最大不相交集的集合?
我考虑过选择所有5套开始。然后,查看每个集合,看看删除该元素是否会影响其余的集合。如果我们带走(3,4,5),它将允许我们保留(4,5,6)和(1,2,3)。因此,其净收益为+1。我们应该从最终列表中删除它。然后,如果我们带走(4,5,6),它将允许我们保持(6,9,10)。净收益为0,因此请勿将其删除。删除(1,2,3)将不会产生任何影响。不要删除它。删除(6,9,10)将允许我们保留(7,8,9)。不确定这是否有意义,但让我知道你的想法!
答案 0 :(得分:1)
如果这三个数字总是连续的,那么这就有一个简单的动态编程解决方案(使用递归公式计算可以使用数字1..i放置的最大值)。
但是,如果此约束并非总是如此,那么这个问题就是NP难。 这是NP难,因为它可以用来解决NP-complete 3-dimensional matching problem。
例如,假设我们匹配X,Y,Z中的元素。我们可以使用数字1 .. | X |为每个允许的匹配构造集合在第一个位置,| X | +1 .. | X | + | Y |在第二个位置和| X | + | Y | .. | X | + | Y | + | Z |在第三位。一旦我们构造了这些集合,我们就可以使用算法解决这个问题来解决三维匹配问题。
答案 1 :(得分:1)
贪婪会这样做。请注意,三元组实际上是间隔,中间数字无关紧要,只有开始/结束时间(即[start, whatever, end]
忽略whatever
使用以下关系顺序对间隔进行排序:
抓住一个堆叠并推送
向下扫描已排序的时间间隔(k
索引是当前的)
最后,您将获得堆叠中非重叠段的最大计数,最左侧位于顶部 - 这是O(N)的空间复杂度。
如果你只需要计算它们,请注意只有堆栈的顶部参与比较,所以你只需要记住堆栈的顶部(每次你弹出/推动替换'栈顶'与当前的一个,让count
保持不变;每次只推动替换'堆栈顶部'并递增计数)。因此,仅计数的空间复杂度为O(1)。
你的例子:
在排序步骤之后,您的间隔为{(1,2,3),(3,4,5),(4,5,6),(7,8,9),( 6,9,10)}
堆栈顶部(6,9,10) - 计数1.以下所有步骤均为展开循环。
拿(7,8,9) - 更保守的开局,逐出堆栈(用旧的)推动当前(用新的) - 堆栈顶部(7,8,9),计数= 1。
(4,5,6) - 比堆栈顶部开始更快结束,收集它 - 堆栈顶部(4,5,6),计数= 2;
(3,4,5) - 较小的开始但与堆栈顶部重叠。贪婪 - 忽略/丢弃。堆栈顶部(4,5,6),count = 2;
(1,2,3) - 比堆栈顶部开始更快结束,收集它 - 堆栈顶部(1,2,3),计数= 3;
向下循环结束,堆栈从上到下读取:{(1,2,3},(4,5,6),(7,8,9)},计数为3。
C ++(未测试)
struct interval { int s; int e; }
struct comparator {
bool operator(const interval& i1, const interval& i2) const {
int i=i1.e-i2.e; // higher ends placed last
if(0==i) { // higher length/lower starts will be higher
i=i2.s-i1.s;
}
return i<0;
}
}
int count_intervals(std::vector<interval>& sets) {
if(sets.empty()) return 0;
comparator comp;
std::sort(sets.begin(), sets.end(), comp);
/* if you need the solution as well, use a stack */
// std::stack<std::vector> solution;
interval& stack_top=sets[sets.size()-1]; // solution.push(stack_top);
int count=1; // we have at least one in the stack
for(int i=sets.size()-2; i>=0; i--) {
interval& curr=sets[i];
if(curr.s > stack_top) { // a better one, lets more room in front
stack_top=curr; // solution.pop(); solution.push(curr);
}
else if(curr.e < stack_top.s) {
stack_top=curr; // solution.push(curr);
count++;
}
}
// if you need the solution, arrange the params of the function to return it
return count;
}