标签:
题目读起来有点晦涩,理解之后思路比较容易想到。其实就是排序的元素换成了闭区间,而闭区间‘相等’就是这些区间有公共的区域(等价类),这样就类似于习题7.2了,返回两个下标,它们之间是相等的元素,前面是‘较小’的区间,后面是‘较大’的区间。那么如何求公共子区间呢,我这里是从前往后遍历数组,如果有交叠,就把主元更新为重叠区域,然后再遍历,这样子如果下一个区间与主元重叠,则该区间与之前所有的区间都重叠。
第二问中如果n个区间都有重叠部分,即n个元素都‘相等’,很显然只需要O(n)的时间,因为第一次划分就结束了排序。
#include <iostream> #include <algorithm> using namespace std; typedef pair<int, int> Interval; //判断两个区间是否重叠 bool Intersect(Interval i1, Interval i2){ return i1.second >= i2.first&&i1.first <= i2.second; } pair<int,int> Interval_P(Interval *inv, int p, int r){ int pivot = p + rand() % (r - p + 1); Interval temp = inv[pivot]; swap(inv[pivot], inv[r]); for (int k = 0; k < r; ++k){ if (Intersect(inv[k], temp)){ temp.first = max(inv[k].first, temp.first); temp.second = min(inv[k].second, temp.second); } } int i = p - 1, j = p; for (; j < r; ++j){ if (!Intersect(inv[j],temp)) if (inv[j].first < temp.first){ ++i; swap(inv[j], inv[i]); } } int t = i+1; for (j = i + 1; j < r; ++j){ if (Intersect(inv[j], temp)) { ++i; swap(inv[i], inv[j]); } } swap(inv[i + 1], inv[r]); return{ t, i + 1 }; } //输入的是数组下标 void Interval_QS(Interval *inv, int p, int r){ if (p >= r) return; pair<int,int> pa= Interval_P(inv, p, r); Interval_QS(inv, p, pa.first - 1); Interval_QS(inv, pa.second + 1, r); } //复习一下尾递归,栈深度的问题 void Tail_IQS(Interval *inv, int p, int r){ while (p < r){ pair<int, int> pa = Interval_P(inv, p, r); Tail_IQS(inv, p, pa.first - 1); p = pa.second + 1; } } int main(){ Interval inv[12] = { { 1, 2 }, { 2, 3 }, { 3, 9 }, { 2, 3 }, { 5, 7 }, { 1, 9 }, { 2, 6 }, { 0, 1 }, { 1, 1 }, { 2, 2 }, { 3, 4 }, {9,10} }; Tail_IQS(inv, 0, 11); for (int i = 0; i < 12; ++i) cout << inv[i].first << " " << inv[i].second<<endl; }
标签:
原文地址:http://www.cnblogs.com/Nastukashii/p/4402163.html