[英]Collection of maximum disjoint sets
給定一組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)。 不知道這是否有意義,但請告訴我您的想法!
如果三個數字始終是連續的,則可以使用簡單的動態編程解決方案(使用遞歸公式使用數字1..i計算可以放置的最大集合)。
但是,如果此約束並不總是正確的,那么這個問題就很難解決。 NP很難,因為它可以用來解決NP完全3維匹配問題 。
例如,假設我們匹配X,Y,Z中的元素。 我們可以使用數字1 .. | X |為每個允許的匹配構建集合。 在第一位置| X | +1 .. | X | + | Y | 在第二位置和| X | + | Y | .. | X | + | Y | + | Z | 在第三位置。 一旦構建了這些集合,我們就可以使用一種算法來解決三維匹配問題。
貪婪會做。 請注意,三胞胎實際上是間隔,中間數無所謂,只有開始/結束才有意義(即在[start, whatever, end]
忽略whatever
使用以下關系順序對時間間隔進行排序:
拿起一疊並推入最后一段
向下掃描排序的間隔( k
索引為當前)
最后,您將獲得堆棧中不重疊段的最大數量,最左側在最上面-這是O(N)的空間復雜度。
如果您只需要計算它們,請注意比較中只涉及堆棧的頂部,因此您只需要記住堆棧的頂部(每次您彈出/推入時,將“堆棧頂部”替換為當前count
保持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),count = 1。
(4,5,6)-在堆棧頂部開始之前結束,收集它-堆棧頂部(4,5,6),count = 2;
(3,4,5)-開始較小,但與堆棧頂部重疊。 貪婪-忽略/丟棄。 堆棧頂部(4,5,6),count = 2;
(1,2,3)-結束於堆棧頂部開始之前,收集它-堆棧頂部(1,2,3),count = 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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.