题目:
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 is2
, 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;
}
};