思路
1.给每个数字一个标记,这个标记代表这个数字所在的第几个集合,把所有数放到一个集合中进行从小到大排序;
2.建立一个滑动窗口,确保窗口内恰好包含的数的标记包含所有集合(这个窗口的数的[左边界数,右边界数]其实就是一个平庸解,因为我们确保了所有集合都在窗口内有它的数字)
3.接下来就很简单了:更新窗口的左边界、右边界,维护一个题意要求的特殊解(即窗口右边界对应的数-左边界对应的数最小)
class Solution {
public:
struct pt
{
int val,pos;
pt(int x,int y)
{
val=x;pos=y;
}
};
vector<pt>ve;
static bool cmp(pt x,pt y)
{
return x.val<y.val;
}
int vis[3505];
vector<int> smallestRange(vector<vector<int>>& nums) {
int SIZE=nums.size();
for(int i=0;i<SIZE;i++)
{
for(int j=0;j<nums[i].size();j++)
{
ve.push_back(pt(nums[i][j],i));
}
}
sort(ve.begin(),ve.end(),cmp);
int lef=0,rig=0,anslef,ansrig;
int n=ve.size();
for(int i=0;i<n;i++)
{
vis[ve[i].pos]++;
bool flag=true;
for(int j=0;j<SIZE;j++)
{
if(!vis[j])
{
flag=false;
break;
}
}
if(flag)
{
rig=i;
break;
}
}
anslef=lef,ansrig=rig;
while(rig<n&&lef<rig)
{
vis[ve[lef].pos]--;
if(vis[ve[lef].pos]!=0)
{
if(ve[rig].val-ve[lef+1].val<ve[ansrig].val-ve[anslef].val)
{
anslef=lef+1;
ansrig=rig;
}
}
else
{
while(vis[ve[lef].pos]==0&&rig+1<n)
{
rig++;
vis[ve[rig].pos]++;
}
if(vis[ve[lef].pos]>0&&ve[rig].val-ve[lef+1].val<ve[ansrig].val-ve[anslef].val)
{
anslef=lef+1;
ansrig=rig;
}
if(vis[ve[lef].pos]==0)break;
}
lef++;
}
vector<int>ans;
ans.push_back(ve[anslef].val);
ans.push_back(ve[ansrig].val);
return ans;
}
};