每日算法 - JavaScript解析:获取最小展台数量
👉 一. 任务描述:
力扣嘉年华将举办一系列展览活动,后勤部将负责为每场展览提供所需要的展台。 已知后勤部得到了一份需求清单,记录了近期展览所需要的展台类型, demand[i][j]
表示第 i 天展览时第 j 个展台的类型。 在满足每一天展台需求的基础上,请返回后勤部需要准备的 最小
展台数量。
注意:
-
同一展台在不同天中可以重复使用。
-
1 <= demand.length,demand[i].length <= 100
-
demand[i][j] 仅为小写字母
/**
* @param {string[]} demand
* @return {number}
*/
var minNumBooths = function(demand) {
...
}
本题取自 leetcode 秋赛题集
》 示例一:
输入:demand = ["acd","bed","accd"]
输出:6
解释:
- 第 0 天需要展台 a、c、d;
- 第 1 天需要展台 b、e、d;
- 第 2 天需要展台 a、
c、c
、d;(由于c类型展台同一天最少需要两台,所以取最大数量)
因此,后勤部准备 abccde 共 6台展台,可以满足每天的展览需求;
》示例二
输入:demand = ["abc","ab","ac","b"]
输出:3
解释:abc每种类型展台任意一天使用台数不超过1台,故只需要 abc各一台。
👉 二. 题意解析
根据题目,可以思考得出,因为限制了 demand[i][j]
仅为小写字母,可以定义两个长度为26的一维数组变量。
一个用于存储全局每种类型的展台所需要使用的台数;另外一个,用于存储每天(局部)中,每种类型展台使用台数,通过比较全局和局部的展台数量,取最多所需的展台数量进行存储。
解题思路
通过 new Array(26).fill(0)
去创建26个字母类型的展台存储数组,通过循环对应天数的展台使用情况,记录每天的使用次数进行比对(Math.max(todayTimes, allTimes)
)
其中,有一个知识点需要记录下,str.charCodeAt(index)
这个函数,它会返回你给定str[index]
字符对应的UTF-8编码。 而因为限制的原因,恰好可以通过 type.charCodeAt() - 97
的方式,获取对应展台类型的位置,进行记录!
具体知识点,可以通过拓展知识去了解。
拓展知识
charCodeAt()
方法可返回指定位置的字符的 UTF-8
编码。这个返回值是 0 - 65535 之间的整数。
方法 charCodeAt()
与 charAt()
方法执行的操作相似,只不过前者返回的是位于指定位置的字符的编码,而后者返回的是字符子串。
例子:
let str = 'abc'
console.log(str.charCodeAt(0)) // returns 97:"a"
console.log(str.charCodeAt(1)) // returns 98:"b"
console.log(str.charCodeAt(2)) // returns 99:"c"
详细点击跳转 👉 UTF-8 C0 控制与基本的 Latin(拉丁字母)
👈
详细点击跳转 👉 String.charCodeAt() 函数 / JavaScript charCodeAt() 方法👈
👉三. 解决方案 ( 如果看不懂,可以配合代码来看,有注释 )
/**
* @param {string[]} demand
* @return {number}
*/
var minNumBooths = function(demand) {
// 方法一 (未改良过,但是思路正确)
// 汇总所有类型展台
let enumCase = [...new Set(demand.join('').split(''))]
for(let showcaseList of demand) {
let showTimes = {}
for(let type of showcaseList.split('')) {
showTimes[type] = showTimes[type] !== undefined ? (showTimes[type] + 1) : 1
showTimes[type] > enumCase.filter(item => item === type).length && enumCase.push(type)
}
}
return enumCase.length
// -------优化前后---------
// 方法二 (改良过,速度快)
// 总共有26种字母,出题的限制(demand[i][j] 仅为小写字母)
/* 如果类型可能是数字或者单个文字,那么方法不如第一种好用。
不过数据不是死的,如果实际运用,肯定是让数据更加明确,比如用二维数组来传入。如:
[
['展台a', '展台2', '展台e', '展台1', '展台5'],
['展台6', '展台22', '展台e', '展台1', '展台y'],
...
]
这样子,那么用第一种方法就更加合适了
*/
let allTypeTimes = new Array(26).fill(0)
for(let showcaseList of demand) {
let currentTypeTimes = new Array(26).fill(0)
for(let type of showcaseList.split('')) {
// 通过charCodeAt获取的是字符对于的UTF-8的对应编码,而因为限制,所有类型均为小写字母
// a 为 起点, UTF-8中,a = 97, 'a'.charCodeAt() = 97 - 97 = 0,
// 和我们一开始定义的大小为26的数值数组对应上,作为每天每种类型展示需要次数存储的变量
currentTypeTimes[type.charCodeAt() - 97] += 1
// 运用Math.max取全局和局部的展示台使用最大台数
allTypeTimes[type.charCodeAt() - 97] = Math.max(currentTypeTimes[type.charCodeAt() - 97], allTypeTimes[type.charCodeAt() - 97])
}
}
return Array.from(allTypeTimes).reduce((prev, cur) => prev + cur)
};
往期内容 💨
🔥 < 每日算法 - Javascript解析:经典弹珠游戏 >
🔥 < 每日算法 - JavaScript解析:从尾到头打印链表 >