1072. 按列翻转得到最大值等行数
题意
- 你可以按列翻转,即 1 -> 0,0 -> 1。
- 在进行若干次翻转后,会有行都为 1 或都为 0 。
- 求这样的行的数量的最大值。
解法1 翻转 + 哈希
这道题的本质是在找最多数量的等价行,等价行指的是在同时进行若干次翻转后,行中只有相同的值,比如说 00010 和 11101 。
由于等价行可能是 0 开头的,也可能是 1 开头的,这会给计数带来困难,所以首先将所有的行都翻转为由 0 开头的,比如说将 00010 和 11101 中的 11101 翻转为 00010。(注意,这里就不是按列翻转了,而是按行翻转)
这样操作以后,如果两个行是等价的,那么他们应当时各元素相等的,因此将它们转化为字符串 string
,通过哈希表进行快速计数。
最后返回出现最多的字符串出现的次数。
官方的写法 通过异或运算来进行翻转,与 1 异或,可以实现翻转,而与 0 异或,值不会发生变化,所以直接与行首数字进行异或,就可以实现上述的操作。
ps. 官方的写法可读性也太差了。
class Solution {
public:
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
unordered_map<string,int> mp;
int ans=0;
int m=matrix.size(),n=matrix[0].size();
// 将所有的行翻转为以0开头,然后利用哈希表,记录每个字符串出现的次数
for(int i=0;i<m;i++)
{
string s="0";
bool flag=false;
if(matrix[i][0]==1) flag=true;
for(int j=1;j<n;j++)
{ // 1开头
if(flag) s = s + to_string(matrix[i][j]^1);
else s = s + to_string(matrix[i][j]);
}
mp[s]+=1;
}
for(unordered_map<string,int>::iterator it=mp.begin();it!=mp.end();it++)
ans = ans>(*it).second?ans:(*it).second;
return ans;
}
};
解法2 翻转 + 哈希 + 异或
class Solution {
public:
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
unordered_map<string,int> mp;
int ans=0;
int m=matrix.size(),n=matrix[0].size();
for(int i=0;i<m;i++)
{
string s(n,'0');
for(int j=0;j<n;j++)
{
s[j] = '0' + (matrix[i][j]^matrix[i][0]); //行首为1的进行翻转,同时转换为字符类型
}
mp[s]+=1;
}
for(auto &[k,v]:mp) //遍历mp
{
ans=max(ans,v);
}
return ans;
}
};
ATTENTION
map
的遍历:for(auto &[k,v]:mp)
int
转string
:to_string(int x)