554. 砖墙
思路:
因为我们要穿过墙,并且要穿过的砖块最少,因此我们应该从从墙缝最多的地方穿过。
那么问题来了,我们如何求得墙缝呢?
每行每个砖头有自己的宽度,墙缝存在两墙块之间,并且每行的总宽度相同,因此我们通过前缀和,来等效求解墙缝。
假设一行砖头宽度为[1,2,2,1],那么缝隙的标号就可以设定为1,1+2,1+2+2.因此该行的墙缝为1,3,5号。为什么没有1+2+2+1=6号呢?因为这是墙的宽度,在边缘不会有任何砖头阻挡,所以题目也说了不能沿墙的垂直边缘穿过。
那么我们整面墙的墙缝号出现的次数越多,我们穿过的砖头就越少。所以我们通过hash表来记录墙缝号和其出现的次数。我们选最大的,并获取其墙缝号,最后遍历每行砖块是否没有出现过这个墙缝号,出现就跳过这行。否则就记一次穿过了一块砖,并跳过这行。
代码:
class Solution {
public:
int leastBricks(vector<vector<int>>& wall) {
unordered_map<int,int> fengxicount;
int height = wall.size();
int maxfengxi=0;
int fengxi=0;
int width_all = 0;
int width0 = wall[0].size();
for(int i=0;i<width0;++i){
width_all+=wall[0][i]; //计算砖墙的边缘
}
for(int i=0;i<height;i++){
int width = wall[i].size();
int presum=0;
for(int j=0;j<width;++j){
presum+=wall[i][j];
if(presum==width_all) break; //跳过墙垂直边缘的情况
fengxicount[presum]++;
if(maxfengxi<fengxicount[presum]){ //获取出现频率最高的墙缝号
fengxi = presum;
maxfengxi=fengxicount[presum];
}
}
}
int res=0;
for(int i=0;i<height;++i){
int width = wall[i].size();
int presum=0;
for(int j=0;j<width;++j){
presum+=wall[i][j];
//每行墙缝号只有小于,大于出现频率最高的墙缝号,可能会等于,所以等于就不会穿过砖头,如果从小于直接到了大于,那么就算穿过了砖块。
if(presum==fengxi) {
break;
}
if(presum>fengxi){
res++;
break;
}
}
}
return res;
}
};