今天做了一到算法题
You have k lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of the k lists.
We define the range [a,b] is smaller than range [c,d] if b-a < d-c or a < c if b-a == d-c.
我的解题思路是,将二维数组中的数据放到一维数组中去,一维数组中的元素为pair<int,int>,first代表value实际值,second代表key值,表示其来自于第几个列表。然后用first当谓词sort一维数组,再用动态规划的办法确定最小范围。
动态规划具体如下:维持一个vsCounts数组,和一个visitedCount变量,当第一次visitedCount==nums.size()的时候,表示此时范围内拥有了来自所有列表内的值。记录下此时的minBegin,和minEnd值,后面每次遍历到当前key值等于当前范围第一个位置的key值的时候,将起始值不断前移,缩小最小范围,缩小到无法缩小时,与历史最小范围比较,将其更新。
这样直到遍历allNums完毕,可得到所求结果。
54ms
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
vector<pair<int,int>>allNums;//first代表value值,second代表key值。
for(int i=0;i<nums.size();++i){//将nums放到一维数组中
for(auto j:nums[i]){
allNums.push_back({j,i});
}
}
sort(allNums.begin(),allNums.end(),[](auto p1,auto p2){return p1.first<p2.first;});//按元素的value值升序排序。
int visitedCount=0;//统计已访问列表种类数
vector<int>vsCounts(nums.size(),0);//记录各列表访问具体次数
int begin=0;//当前范围起始点,当前范围结束点由下方循环中的k代替。
int minBegin=0;//最小范围起始点
int minEnd=allNums.size()-1;//最小范围结束点
for(int k=0;k<allNums.size();++k){
int id=allNums[k].second;
if(vsCounts[id]==0){
++visitedCount;
++vsCounts[id];
}else{
++vsCounts[id];
if(id==allNums[begin].second){//如果等于当前范围的起始点,则更新起始点
while(vsCounts[allNums[begin].second]>1){
--vsCounts[allNums[begin].second];
++begin;
}
}else{//没有更新的话就跳过。
continue;
}
}
if(visitedCount==nums.size()){//所有列表都在范围内,更新最小范围。
if(allNums[k].first-allNums[begin].first<allNums[minEnd].first-allNums[minBegin].first){
minBegin=begin;
minEnd=k;
}
}
}
vector<int>res{allNums[minBegin].first,allNums[minEnd].first};
return res;
}
};