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;

    }
};
posted @ 2021-05-12 16:33  Mrsdwang  阅读(83)  评论(0编辑  收藏  举报