你的面前有一堵矩形的、由 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

暴力法

首先这道题我的第一想法,是对这面砖墙的数组做优化处理
因为传入的wall的数据,第二维中个数参差不齐,对于计算时会有影响
如果根据每个数字代表占多少个位置处理,那么这面墙就会是N x M的规范数组了
对于示例1,数组会处理成:

原始:
[[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]
]处理后:
[[1,2,2,2,2,1],[3,3,3,1,2,2],[1,3,3,3,2,2],[2,2,4,4,4,4],[3,3,3,1,2,2],[1,3,3,3,1,1]
]

处理后的数据如何判断是两块砖的缝隙?那么就通过循环,判断前后是否是同一个数字即可。
但上面处理后的数据,则发现,如果相邻的两块砖的长度一致,则无法判断是否是否有缝隙。
于是,wall数组处理方式更改一下,在循环wall的时候,就判断前后砖头是否有空隙,以0,1来分割,即:

原始:
[[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]
]处理后:
[[ 0, 1, 1, 0, 0, 1 ],[ 0, 0, 0, 1, 0, 0 ],[ 0, 1, 1, 1, 0, 0 ],[ 0, 0, 1, 1, 1, 1 ],[ 0, 0, 0, 1, 0, 0 ],[ 0, 1, 1, 1, 0, 1 ]
]

这样就可以清楚知晓是否有缝隙了,此时再遍历每一个纵线(根据题目,除第0列的左侧,及最后一列的右侧属于非遍历列外,其余皆需要判断),判断前后数字是否一致,不一致+1,用一个一维数组存储,然后用Math.min()方法去判断所需要的划过最少的砖块数量。

代码:

function leastBricks(wall: number[][]): number {const columns = wall[0].reduce((prev, curr) => prev + curr, 0)if (columns < 2) return wall.lengthconst formatWall = new Array(wall.length).fill(0).map(item => new Array(columns).fill(0))wall.forEach((row, rowIndex) => {let index = 0let value = 0row.forEach((num, columnIndex) => {for (let i = 0; i < num; i++) {formatWall[rowIndex][index] = valueindex++}value = value === 0 ? 1 : 0})})const rowAmount = formatWall.lengthconst columnAmount = formatWall[0].lengthconst result = new Array(columnAmount - 1).fill(0)for (let i = 0; i < columnAmount - 1; i++) {for (let j = 0; j < rowAmount; j++) {if (formatWall[j][i] === formatWall[j][i + 1]) {result[i]++}}}return Math.min(...result)
};

当我通过本地的几个示例后,我提交了,但发现并没有AC
提示我:FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
而对应的传入数据为:[[100000000],[100000000],[100000000]]
再看下题目中提示:

n == wall.length
1 <= n <= 10^4
1 <= wall[i].length <= 10^4
1 <= sum(wall[i].length) <= 2 * 10^4
对于每一行 i ,sum(wall[i]) 应当是相同的
1 <= wall[i][j] <= 2^31 - 1

超出内存限制,因此暴力法不可取

哈希表

既然暴力法无法处理,那么作为程序员,第一个反应应该就是反向思考
还是看示例1的图片:

我们发现黄色线在03行穿过了砖块,但也发现1245就是缝隙所在的行数,这两者数量之和就是墙的高度
被穿过的砖块所在的列并不好计算,但缝隙所在indexwall数组中简单求和即可得出的
因此对于数组,处理后结果如下:

原始:
[[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]
]处理后:
[[ 1, 3, 5, 6],[ 3, 4, 6 ],[ 1, 4, 6 ],[ 2, 6 ],[ 3, 4, 6],[ 1, 4, 5, 6 ]
]

根据题目的说明,最后一列的缝隙index忽略

此时,我们计算每个缝隙出现的次数,然后用墙的高度wall.length相减其中最多的次数,即可得到可穿过最短砖块的数量
而存储每个缝隙出现的次数时,一个是使用数组,以下标记录缝隙的index,但因为缝隙数字可能会非常大,所以使用哈希表


JS中,新的ES6(其实也不新了) 规范中,有了一个Map数据类型,就是哈希表
对于其功能阐述,在这里不做赘述,请参见阮一峰老师的《ECMAScript 6 入门教程》中对Map的说明:地址


根据这个思路,代码改为:

function leastBricks(wall: number[][]): number {const count = new Map()for (const row of wall) {let sum = 0for (let i = 0; i < row.length - 1; i++) {sum += row[i]count.set(sum, (count.has(sum) ? count.get(sum) : 0) + 1)}}let maxCount = 0for (const [_, amount] of count.entries()) {maxCount = Math.max(amount, maxCount)}return wall.length - maxCount
};

提交后AC,耗时92ms,在所有 TypeScript 提交中击败了 96.61% 的用户

综上所述

  1. 暴力法是初学者第一个想到的方法,有些时候暴力法可以解决一部分问题,幸运的话可以AC,但暴力法不是解决问题最好的途径,但却是初学者走上算法之路的必经途径;
  2. 暴力法无法解决的问题,则一般情况下需要反向思考,如何动用最少的资源与复杂度去解决问题,如何根据题目中给予的数据,找出作者的暗示,也是很重要的一点;
  3. 当有一定的算法经验后,暴力法则不是优先使用的方法了,所以还是需要多多练习。

[20210502]LeetCode每日一题 - 554. 砖墙相关推荐

  1. LeetCode每日抑题 554. 砖墙

    554. 砖墙 难度:中等 语言:java 题目内容 你的面前有一堵矩形的.由 n 行砖块组成的砖墙.这些砖块高度相同(也就是一个单位高)但是宽度不同.每一行砖块的宽度之和应该相等. 你现在要画一条 ...

  2. leetcode每日刷题计划-简单篇day8

    leetcode每日刷题计划-简单篇day8 今天是纠结要不要新买手机的一天QAQ想了想还是算了吧,等自己赚钱买,加油 Num 70 爬楼梯 Climbing Stairs class Solutio ...

  3. Leetcode每日一题:171.excel-sheet-column-number(Excel表列序号)

    思路:就是168题的反命题,进制的方式完美解决: Leetcode每日一题:168.excel-sheet-column-title(Excel表名称) class Solution {public: ...

  4. 【LeetCode每日一题】1723. 完成所有工作的最短时间

    [LeetCode每日一题]1723. 完成所有工作的最短时间 [1] 1723. 完成所有工作的最短时间 [2] 473. 火柴拼正方形 [1] 1723. 完成所有工作的最短时间 题目: 给你一个 ...

  5. leetcode每日一题--雀巢原理;抽屉算法;Quorum机制;分布式应用

    leetcode每日一题 539. 最小时间差 示例 1: 输入:timePoints = ["23:59","00:00"] 输出:1 示例 2: 输入:ti ...

  6. LeetCode每日一题——1812. 判断国际象棋棋盘中一个格子的颜色

    LeetCode每日一题系列 题目:1812. 判断国际象棋棋盘中一个格子的颜色 难度:简单 文章目录 LeetCode每日一题系列 题目 示例 思路 题解 题目 给你一个坐标 coordinates ...

  7. 【LeetCode每日一题】——109.有序链表转换二叉搜索树

    文章目录 一[题目类别] 二[题目难度] 三[题目编号] 四[题目描述] 五[题目示例] 六[题目提示] 七[解题思路] 八[时间频度] 九[代码实现] 十[提交结果] 一[题目类别] 二叉树 二[题 ...

  8. leetcode每日一题·救生艇问题(Python)

    leetcode每日一题·救生艇问题(Python) 问题描述 题目入口 题目思路 首先分析问题,一个船最多坐两人,因此我们可以把这个问题看作两两组合的问题,并且如果最重的那个人和最轻的人加起来大于l ...

  9. LeetCode每日一题——904. 水果成篮

    LeetCode每日一题系列 题目:904. 水果成篮 难度:普通 文章目录 LeetCode每日一题系列 题目 示例 思路 题解 题目 你正在探访一家农场,农场从左到右种植了一排果树.这些树用一个整 ...

最新文章

  1. GigaScience:ASaiM基于Galaxy微生物组分析框架
  2. boost::geometry::cross_product用法的测试程序
  3. javascript 库_您应该在2020年尝试的10个很棒JavaScript库
  4. iOS项目工程添加.a文件遇到的Dsymutil Error
  5. Android用表格布局做菜单栏,Android开发菜单布局之表格布局示例
  6. 关于简历:怎样才叫熟悉/精通Linux?
  7. 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(二)
  8. 谷歌翻译突然用不了了
  9. 小白日更第二十九天->DNS域名解析
  10. PHP基础学习第十四篇(了解和使用PHP的数据类型、常量、字符串变量、运算符)
  11. Mac Catalina系统关闭/打开开机duang音效
  12. c语言二级程序设计题难吗,c语言二级公共基础知识试题特点
  13. 仿淘宝商品界面(html div+css)
  14. 写500字关于漫威英雄的论文
  15. 中文自动文本摘要生成指标计算,Rouge/Bleu/BertScore/QA代码实现
  16. android执行lua脚本的方法,android执行lua脚本的方法
  17. 《万历十五年》 黄仁宇
  18. 数据模型篇之大数据领域建模综述
  19. 机智云物联网荣获“2021年度广州创新力大奖”
  20. python远程方法调用_Python远程方法调用 RPyC

热门文章

  1. 新加坡行前——上海一日游 13/09/2012
  2. ppt文件大图标界面如何显示预览图
  3. 亚马逊云科技 Build On---基于Serverless 构建创新零售应用
  4. 无线体温监测系统的设计
  5. 基于 JavaWeb 的在线书城项目
  6. 从古至今的计算机设备,从古至今的计算工具
  7. 德州仪器:适用于高电流应用的电池测试仪参考设计TIDA-01040
  8. 8Manage:电子寻源采购管理指南
  9. 信用卡什么原因会被冻结
  10. 2019年Python入门书籍推荐