2055. Plates Between Candles

题目:

There is a long table with a line of plates and candles arranged on top of it. You are given a 0-indexed string s consisting of characters '*' and '|' only, where a '*' represents a plate and a '|' represents a candle.

You are also given a 0-indexed 2D integer array queries where queries[i] = [lefti, righti] denotes the substring s[lefti...righti] (inclusive). For each query, you need to find the number of plates between candles that are in the substring. A plate is considered between candles if there is at least one candle to its left and at least one candle to its right in the substring.

  • For example, s = "||**||**|*", and a query [3, 8] denotes the substring "*||**|". The number of plates between candles in this substring is 2, as each of the two plates has at least one candle in the substring to its left and right.

Return an integer array answer where answer[i] is the answer to the ith query.

Example 1:

Input: s = "**|**|***|", queries = [[2,5],[5,9]]
Output: [2,3]
Explanation:
- queries[0] has two plates between candles.
- queries[1] has three plates between candles.

Example 2:

Input: s = "***|**|*****|**||**|*", queries = [[1,17],[4,5],[14,17],[5,11],[15,16]]
Output: [9,0,0,0,0]
Explanation:
- queries[0] has nine plates between candles.
- The other queries have zero plates between candles.

Constraints:

  • 3 <= s.length <= 105
  • s consists of '*' and '|' characters.
  • 1 <= queries.length <= 105
  • queries[i].length == 2
  • 0 <= lefti <= righti < s.length

思路:

比较新的题,大致上是一道小dp。题意是 '*' 代表盘子而 '|' 代表蜡烛,给定一个字符串,找出给定区间[a, b]中夹在两个蜡烛之间的盘子总数。对于给定区间,我们首先要找到区间内最左边和最右边的蜡烛,因为区间[a, b]是封闭的,s[a]和s[b]作为区间的边界是蜡烛,里面的所有盘子就都是。但是如果区间内无蜡烛,那么里面的所有盘子都不是。首先如何快速找蜡烛?用两个vector进行记录,left记录当前i在s[i]的左边第一根蜡烛index,如果s[i]本身就是蜡烛的话,left[i]的值就应该是i,如果左边没有蜡烛,则初始化为-1;同理,right记录当前i在s[i]的右边第一根蜡烛的index。之后就是个一维dp,也是前缀和,dp[i]是从左数到目前为止共有几个盘子。递推公式为如果当前s[i]是蜡烛,那么dp[i] = dp[i - 1],否则就是dp[i] = dp[i - 1] + 1。这里因为计算left的时候和计算dp的时候都是从左往右遍历,因此放在同义词pass中了。最后对于任意给定区间[a, b],从left中找到b左边的第一根蜡烛,从right中找到a右边的第一根蜡烛,这时分类讨论:如果左边或者右边蜡烛为-1,则想当于区间内只有0或者1根蜡烛,不成立,直接0个盘子即可;如果左边蜡烛的index比右边蜡烛的index大,相当于右边或者左边的蜡烛超出了边界,其实也是只有0或者1根蜡烛(可以看example2的[4, 5]区间,右边蜡烛为6,左边蜡烛为3,区间内无蜡烛),也是不成立的;其余情况总数即为dp[右边蜡烛index] - dp[左边蜡烛index]。

代码:

class Solution {
public:
    vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
        int n = s.size();
        vector<int> left(n), right(n), dp(n);
        int l = -1, r = -1;
        for (int i = 0; i < n; i++) {
            if (s[i] == '|') 
                l = i;
            left[i] = l;
            dp[i] = s[i] == '*' ? 1 : 0;
            if (i > 0)
                dp[i] += dp[i - 1];
        }
        for (int i = n - 1; i >= 0; i--) {
            if (s[i] == '|')
                r = i;
            right[i] = r;
        }
        vector<int> res;
        for (auto& q : queries) {
            l = right[q[0]];
            r = left[q[1]];
            if (l >= r || l == -1 || r == -1) {
                res.push_back(0);
            } else 
                res.push_back(dp[r] - dp[l]);
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值