又是熟悉的二维矩阵,之前的学习中知道,我们可以对每一行使用二分来得到每行的战斗力,问题就在于如何把战斗力从小到大排序的同时还保留它们的下标位置呢?
注意到数据范围最大是100,也就是说下标最大是99,那么假设战斗力为p,下标为i
我们令n=p*100+i,这样的话我们可以用n/100来得到战斗力p,用n%100来得到下标i,我们将每行的n储存起来再排序,很容易得到这样的排序其实是按战斗力排的,然后就可以返回前k项解决此题。
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
vector<int> ans,fz;
int m=mat.size(),n=mat[0].size();
for(int i=0;i<m;i++){
int p=0,q=n;
while(p<q){
int mid=(p+q)/2;
if(mat[i][mid]==1){
p=mid+1;
}
else{
q=mid;
}
}
fz.push_back(p*1000+i);
}
sort(fz.begin(),fz.end());
for(int i=0;i<k;i++){
ans.push_back(fz[i]%1000);
}
return ans;
}
};
这里写的时候顺手乘了个1000,不过无伤大雅。
注意到arr是无序排列的,想用二分还得给他排个序
排好序后一看,欸,一维查找这么简单,啪的一下就写好交上去了,一看红了,才发现arr里 有负数,原来坑点在这,不过没关系,加个分类讨论就过了。
class Solution {
public:
bool checkIfExist(vector<int>& arr) {
sort(arr.begin(),arr.end());
int n=arr.size();
for(int i=0;i<n;i++){
if(arr[i]*2>arr[n-1]){
break;
}
if(arr[i]>0){
int p=i+1,q=n;
while(p<q){
int mid=(p+q)/2;
if(arr[mid]==2*arr[i]){
return 1;
}
else if(arr[mid]>2*arr[i]){
q=mid;
}
else{
p=mid+1;
}
}
}
else{
int p=0,q=i;
while(p<q){
int mid=(p+q)/2;
if(arr[mid]==2*arr[i]){
return 1;
}
else if(arr[mid]>2*arr[i]){
q=mid;
}
else{
p=mid+1;
}
}
}
}
return 0;
}
};