题目描述:
给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了。请你帮忙找出在所有这些行中 最小的公共元素。
如果矩阵中没有这样的公共元素,就请返回 -1。
示例:
输入:mat = [[1,2,3,4,5],[2,4,5,8,10],[3,5,7,9,11],[1,3,5,7,9]]
输出:5
提示:
1 <= mat.length, mat[i].length <= 500
1 <= mat[i][j] <= 10^4
mat[i] 已按递增顺序排列。
方法1:
主要思路:解题链接汇总
(1)先找出数组中每行的首个值的最大值和最后一个值的最小值,保证首个值的最大值小于等于最后一个值的最小值;
(2)使用上述求出的两个值作为范围,将第一行内的在两个值范围内的值存入到st中;
(3)后面处理各个行时,同样使用之前确定的相同范围的最大值和最小值来确定当前行要处理的范围,并将同样出现在st中的值,使用另一个st统计;
(4)最后将st进行更新,作为新的交集st,判断下一行;
class Solution {
public:
int smallestCommonElement(vector<vector<int>>& mat) {
int max_begin=INT_MIN,min_end=INT_MAX;
for(vector<int>&m:mat){//找出各个行的首个值的最大值和最后一个值的最小值,确定初始的交集范围
max_begin=max(max_begin,m[0]);
min_end=min(min_end,m.back());
}
if(min_end<max_begin){//说明没有交集
return -1;
}
unordered_set<int> st;//使用第一行,确定初始的交集范围
auto it=lower_bound(mat[0].begin(),mat[0].end(),max_begin);
int cur_min=INT_MAX,cur_max=INT_MIN;//确定交集中的最大值和最小值
while(it!=mat[0].end()&&(*it)<=min_end){
st.insert(*it);
cur_max=*it;
if(cur_min==INT_MAX){
cur_min=*it;
}
++it;
}
for(int i=1;i<mat.size();++i){//和后面的各个行求交集
auto it=lower_bound(mat[i].begin(),mat[i].end(),cur_min);//当前范围的初始位置
if(it==mat[i].end()){//说明没有交集了
return -1;
}
//存储当前交集和当前行的新的交集
unordered_set<int> tmp_st;
//保留新的交集的最小值和最大值
int tmp_min=INT_MAX,tmp_max=INT_MIN;
while(it!=mat[i].end()&&(*it)<=cur_max){
if(st.count(*it)){//当前值是交集
tmp_st.insert(*it);
tmp_max=*it;
if(tmp_min==INT_MAX){
tmp_min=*it;
}
}
++it;
}
//不存在交集
if(tmp_st.empty()){
return -1;
}
//更新交集
st=tmp_st;
//更新交集的最大值和最小值
cur_min=tmp_min;
cur_max=tmp_max;
}
//返回交集的最小值
return cur_min;
}
};