题目描述:
给定由若干 0 和 1 组成的矩阵 matrix,从中选出任意数量的列并翻转其上的 每个 单元格。翻转后,单元格的值从 0 变成 1,或者从 1 变为 0 。
回经过一些翻转后,行与行之间所有值都相等的最大行数。
示例 1:
输入:[[0,1],[1,1]]
输出:1
解释:不进行翻转,有 1 行所有值都相等。
示例 2:
输入:[[0,1],[1,0]]
输出:2
解释:翻转第一列的值之后,这两行都由相等的值组成。
示例 3:
输入:[[0,0,0],[0,0,1],[1,1,0]]
输出:2
解释:翻转前两列的值之后,后两行由相等的值组成。
提示:
1 <= matrix.length <= 300
1 <= matrix[i].length <= 300
所有 matrix[i].length 都相等
matrix[i][j] 为 0 或 1
方法1:
主要思路:解题链接汇总
(1)找出各个行相同的和完全不相同的行作为一组,分组中数量最多的行数即为结果;
(2)完全不相同的行,刚好可以通过改变一半的值获得相同的数字分布;
class Solution {
public:
bool not_same(vector<vector<int>>&matrix,int i,int j){//判断两行是否完全不相同
for(int k=0;k<matrix[0].size();++k){
if(matrix[i][k]==matrix[j][k]){
return false;
}
}
return true;
}
bool same(vector<vector<int>>&matrix,int i,int j){//判断两行是否完全相同
return matrix[i]==matrix[j];
}
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
vector<bool> visited(matrix.size(),false);//标识访问过的行
int res=0;
int cur=0;
for(int i=0;i<matrix.size();++i){
if(visited[i]){//跳过访问过的行
continue;
}
visited[i]=true;//标识访问过的行
++cur;//新的一组
for(int j=0;j<matrix.size();++j){
if(visited[j]){
continue;
}
if(not_same(matrix,i,j)||same(matrix,i,j)){
visited[j]=true;
++cur;
}
}
//根据当前组的数量,更行可能的更大的组数
res=max(res,cur);
cur=0;
}
return res;
}
};
方法2:
主要思路:
(1)哈希;
(2)主要判读思想和方法一一致,就是将完全相同的和完全不相同的行统一为一组;
(3)只不过,这里将行转为对应的字符串,并根据每行的首个数字的状态,决定转换的方式;
class Solution {
public:
int maxEqualRowsAfterFlips(vector<vector<int>>& matrix) {
unordered_map<string,int> mp;
for(vector<int>&cur_row:matrix){
string cur_str;
if(cur_row[0]==1){
for(int& i:cur_row){
if(i==1){
cur_str+='1';
}
else{
cur_str+='0';
}
}
}
else{
for(int& i:cur_row){
if(i==1){
cur_str+='0';
}
else{
cur_str+='1';
}
}
}
++mp[cur_str];
}
int res=0;
for(auto&it:mp){
res=max(res,it.second);
}
return res;
}
};