leetcode刷题记录-2055. 蜡烛之间的盘子

384 阅读2分钟

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:

image.png

输入:s = "**|**|***|", queries = [[2,5],[5,9]] 输出:[2,3] 解释:

  • queries[0] 有两个盘子在蜡烛之间。
  • queries[1] 有三个盘子在蜡烛之间。 示例 2:

image.png

输入: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

题解

动态规划

首先我们要了解一下题目的要求,在一个字符串之中取一个区间,然后去这个区间里面找到被蜡烛夹起来的盘子。

寻找左右的蜡烛

这样我们能够知道,在找到的这个区间里面,我们只要找到最左边和最右边的蜡烛,那么中间无论还有几个蜡烛,中间的盘子全都是满足题目要求的。

image.png

比如上面这个字符串,在最左边和最右边的蜡烛中间,所以的盘子都满足条件。

计算区间中盘子的数量

在我们知道了我们要取的蜡烛围起来的区间之后,我们剩下的就是要去计算这个区间的盘子数量,我们可以用一个数组,遍历一遍字符串,把每个位置的盘子数量用一个数组存起来:

image.png

比如刚刚那个字符串,我们就是可以用这样一个数组来把每个位置的值保存下来,然后在我们需要某个区间的盘子数量的时候,我们只要那这个区间的右边值减去左边值就可以了。

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;
};

image.png