Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
前言
今天的题目为中等,题目的解法有很多种,但是大多的思路还是一样的,本文通过预处理将时间复杂度尽量减低到了 O(n)。
每日一题
今天的每日一题 2055. 蜡烛之间的盘子,难度为中等
-
给你一个长桌子,桌子上盘子和蜡烛排成一列。给你一个下标从 0 开始的字符串 s ,它只包含字符 '*' 和 '|' ,其中 '*' 表示一个 盘子 ,'|' 表示一支 蜡烛 。
-
同时给你一个下标从 0 开始的二维整数数组 queries ,其中 queries[i] = [lefti, righti] 表示 子字符串 s[lefti...righti] (包含左右端点的字符)。对于每个查询,你需要找到 子字符串中 在 两支蜡烛之间 的盘子的 数目 。如果一个盘子在 子字符串中 左边和右边 都 至少有一支蜡烛,那么这个盘子满足在 两支蜡烛之间 。
-
比方说,s = "||**||**|*" ,查询 [3, 8] ,表示的是子字符串 "*||**|" 。子字符串中在两支蜡烛之间的盘子数目为 2 ,子字符串中右边两个盘子在它们左边和右边 都 至少有一支蜡烛。 请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。
示例 1:
输入:s = "**|**|***|", queries = [[2,5],[5,9]] 输出:[2,3] 解释:
- queries[0] 有两个盘子在蜡烛之间。
- queries[1] 有三个盘子在蜡烛之间。 示例 2:
输入:s = "***|**|*****|**||**|*", queries = [[1,17],[4,5],[14,17],[5,11],[15,16]] 输出:[9,0,0,0,0] 解释:
- queries[0] 有 9 个盘子在蜡烛之间。
- 另一个查询没有盘子在蜡烛之间。
提示:
- 3 <= s.length <= 105
- s 只包含字符 '*' 和 '|' 。
- 1 <= queries.length <= 105
- queries[i].length == 2
- 0 <= lefti <= righti < s.length
题解
动态规划
首先我们要了解一下题目的要求,在一个字符串之中取一个区间,然后去这个区间里面找到被蜡烛夹起来的盘子。
寻找左右的蜡烛
这样我们能够知道,在找到的这个区间里面,我们只要找到最左边和最右边的蜡烛,那么中间无论还有几个蜡烛,中间的盘子全都是满足题目要求的。
比如上面这个字符串,在最左边和最右边的蜡烛中间,所以的盘子都满足条件。
计算区间中盘子的数量
在我们知道了我们要取的蜡烛围起来的区间之后,我们剩下的就是要去计算这个区间的盘子数量,我们可以用一个数组,遍历一遍字符串,把每个位置的盘子数量用一个数组存起来:
比如刚刚那个字符串,我们就是可以用这样一个数组来把每个位置的值保存下来,然后在我们需要某个区间的盘子数量的时候,我们只要那这个区间的右边值减去左边值就可以了。
const n = s.length;
const plates = new Array(n).fill(0);
for (let i = 0, platesSum = 0; i < n; i++) {
if (s[i] === "*") {
platesSum++;
}
plates[i] = platesSum;
}
解题
在知道盘子的数量,以及左右两边的蜡烛的位置之后,我们还需要做一个特殊情况处理,就是当左右两边有一边是没有蜡烛的,那么,我们就可以把没出现过蜡烛的位置都用 -1 来表示。
/**
* @param {string} s
* @param {number[][]} queries
* @return {number[]}
*/
var platesBetweenCandles = function (s, queries) {
let n = s.length;
// 省去保存盘子数量数组计算
let left = new Array(n).fill(-1);
for (let i = 0, l = -1; i < n; i++) {
if (s[i] === "|") {
l = i;
}
left[i] = l;
}
let right = new Array(n).fill(-1);
for (let i = n - 1, r = -1; i >= 0; i--) {
if (s[i] === "|") {
r = i;
}
right[i] = r;
}
let res = new Array(queries.length).fill(0);
for (let i = 0; i < queries.length; i++) {
let querie = queries[i];
let x = right[querie[0]]
let y = left[querie[1]];
res[i] = x === -1 || y === -1 || x >= y ? 0 : plates[y] - plates[x];
}
return res;
};