数据范围是3500,3500也就是说n的平方是可以接受的。这里告诉你就是有序的,也就是在提醒你可能会是一个类似于二分的算法,所以的话其实基于这两个认识的话我们就可以利用一个枚举叫二分的算法来解决这道题。怎么做呢?就首先的话我们要枚举一端,一端的话我们可以把所有的这个lists的里面所有元素都给去重然后对它进行左端的一个枚举,然后右端的话的呢我们就分别对每一个list进行一个二分来查找它可能包含所有至少来查找这个至少包含一个元素的最大的这么一个区间是什么。然后我们每次枚举的时候把这些最大的区间找一个最小的出来,这就是我们所需要的一个答案。那么这个整个复杂度的话应该是k的平方乘以一个log所有lists里面最大的一个,所有lists里面一个最长的元素n,所以应该是k^2*logn,这个复杂度是可以接受的。
首先呢是要对这个我们要对就要枚举的这个元素进行去重,这样我们就可以减少这个运算量。这里呢我用一种可能大家不怎么熟悉的一种去重的方法,就是用一个sort+unqiue这个方法来进行去重。然后unique的话呢是用于一个有序的数组的一个去重的方法。然后unique它返回的这个东西的下标,就最后一个元素的下标。然后注意的话这个unique的话,也就是对有序的、就是已经排好序的这么一个数组才能进行去重,不然的话它就有可能返回一个错误的结果。
这样我们就得到了它在已经去重之后的这个vi的区间是在哪儿,所以的话我们就可以来进行枚举了。枚举的话呢我们就直接就遍历到offset就行。offset是去重之后的vi的区间。注意一下这个unique去重之后是一个左闭右开的一个区间,就是STL的一个惯例。然后的话我们这个区间我们还得定义一下这个区间的话可能那个最大值就是是多少,我们最大值肯定是排完序之后的,左边的话它肯定是它的那个最小值,所以我们这边就直接用这个排好序之后的一个最小值以及排好序之后的最大值,就这里减1,因为是左闭右开。然后这里应该是枚举的话我们先把这个区间锁定在一个秩上面,最后我们来进行一个扩展,然后之后再跟大L、跟大R进行比较。然后我们有时候的话我们可能枚举的话可能是找不到一个合适的值,比如说我们如果是拿26去枚举的话,我们就肯定就,20、26作为它的那个左边那个值的话是肯定得不到一个正确的值的。比如说26到哪儿都,到30的话肯定是覆盖不了所有的区间的,所以的话那我们要定义一个布尔变量来判断一下我们是否是不是能找到这个值,所以的话我们就开始遍历所有的vector,然后的话,我们这里要用lower_bound,就是说找到第一个出现、第一次出现的地方,这样的话才是我们所需要的那个最小的区间。因为的话我们每次枚举的话肯定都是要找一个最大符合的,我们不是找最小符合的,就最小符合的话可能就其它区间就不会满足了,这样的话我们才有机会覆盖所有的,就我们以l这个值为枚举的话,我们才有可能找到这个r,l到r的话可以覆盖所有的这个区间。
class Solution { public:vector<int> smallestRange(vector<vector<int>>& nums) {//sort+unique [1,1,1,2,3,3]->[1,2,3,XXXXXX]//vector<int> vi,rt;vector<int> vi;for (auto& i:nums) {for (auto j:i) {vi.push_back(j); }}sort(vi.begin(), vi.end());//vector<int>::iterator offset= unique(vi.begin(),vi.end());int L = *vi.begin();//int R = *vi.end()-1;int R = *(vi.end() - 1);int offset = unique(vi.begin(), vi.end()) - vi.begin();for (int i = 0;i < offset;i++) {int l = vi[i];int r = vi[i];bool find = false;for (auto& j : nums) {auto iter = lower_bound(j.begin(),j.end(),l);if (iter != j.end()) {find = true;r = max(*iter,r);}else {find = false;break;}}if (find) {if ((r -l<R-L)||(l<L&&r-l==R-L)) {L = l;R = r;}}}//rt.push_back(vi[L]);//rt.push_back(vi[R]);//return rt;return { L,R };} };