题目链接:
力扣https://leetcode-cn.com/problems/plates-between-candles/
【分析】这道题一开始想着记录每个蜡烛区间的盘子数,做一个[start, end]->num的映射,但是对于每一个区间的查询都需要遍历所有的区间,判断左右端点是否在区间内,显然超时了。
看了题解后发现需要进行预处理,即对于每个位置都找到离他最近的左蜡烛和右蜡烛,这样对于区间[i,j]来说,找i处右边第一个蜡烛和j处左边第一个蜡烛。现在能把区间缩小到两个蜡烛[k,l]之间了,那么继续计算出每个位置处盘子数量的和,用l处的总盘子数-k处的总盘子数就是答案了。
class Solution {
public int[] platesBetweenCandles(String s, int[][] queries) {
int n = s.length();
int i, j;
int[] lefts = new int[n];
Arrays.fill(lefts, -1);
lefts[0] = (s.charAt(0) == '|' ? 0: -1);
for(i = 1; i < n; i++){
if(s.charAt(i) == '|') lefts[i] = i;
else lefts[i] = lefts[i - 1];
}
int[] rights = new int[n];
Arrays.fill(rights, -1);
rights[n - 1] = (s.charAt(n - 1) == '|' ? n - 1: -1);
for(i = n - 2; i >= 0; i--){
if(s.charAt(i) == '|') rights[i] = i;
else rights[i] = rights[i + 1];
}
int[] cnt = new int[n];
if(s.charAt(0) == '*') cnt[0] = 1;
for(i = 1; i < n; i++){
if(s.charAt(i) == '*') cnt[i] = cnt[i - 1] + 1;
else cnt[i] = cnt[i - 1];
}
n = queries.length;
int[] ans = new int[n];
int left, right;
for(i = 0; i < n; i++){
right = lefts[queries[i][1]];
left = rights[queries[i][0]];
if(left == -1 || right == -1 || right < left) ans[i] = 0;
else ans[i] = cnt[right] - cnt[left];
}
return ans;
}
}