算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
今天和大家聊的问题叫做 砖墙,我们先来看题面:
https://leetcode-cn.com/problems/brick-wall/
There is a rectangular brick wall in front of you with n rows of bricks. The ith row has some number of bricks each of the same height (i.e., one unit) but they can be of different widths. The total width of each row is the same.
Draw a vertical line from the top to the bottom and cross the least bricks. If your line goes through the edge of a brick, then the brick is not considered as crossed. You cannot draw a line just along one of the two vertical edges of the wall, in which case the line will obviously cross no bricks.
Given the 2D array wall that contains the information about the wall, return the minimum number of crossed bricks after drawing such a vertical line.
你的面前有一堵矩形的、由 n 行砖块组成的砖墙。这些砖块高度相同(也就是一个单位高)但是宽度不同。每一行砖块的宽度之和相等。
你现在要画一条 自顶向下 的、穿过 最少 砖块的垂线。如果你画的线只是从砖块的边缘经过,就不算穿过这块砖。你不能沿着墙的两个垂直边缘之一画线,这样显然是没有穿过一块砖的。
给你一个二维数组 wall ,该数组包含这堵墙的相关信息。其中,wall[i] 是一个代表从左至右每块砖的宽度的数组。你需要找出怎样画才能使这条线 穿过的砖块数量最少 ,并且返回 穿过的砖块数量 。
示例
示例 1:
输入:wall = [[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]]
输出:2
示例 2:
输入:wall = [[1],[1],[1]]
输出:3
解题
https://www.cnblogs.com/Mrsdwang/p/14760420.html
因为我们要穿过墙,并且要穿过的砖块最少,因此我们应该从从墙缝最多的地方穿过。
那么问题来了,我们如何求得墙缝呢?
每行每个砖头有自己的宽度,墙缝存在两墙块之间,并且每行的总宽度相同,因此我们通过前缀和,来等效求解墙缝。
假设一行砖头宽度为[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;
}
};
好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。
上期推文: