一开始的思路是找到区间内第一个蜡烛和最后一个蜡烛,最后计算这两个蜡烛之间的盘子数量,当然超时了。
那么怎么去优化这两个步骤呢,第一个步骤我采取了记录蜡烛位置的方式,通过二分查找区间上下限,定位到第一个蜡烛和最后一个蜡烛的下标;第二个步骤我采取前缀和数组的方式,记录前i个元素中盘子的个数。
class Solution {
public int[] platesBetweenCandles(String s, int[][] queries) {
int m = queries.length;
int[] ans = new int[m];
int[] pre = new int[s.length()];
List<Integer> list = new ArrayList<>();
if(s.charAt(0) == '*') {
pre[0] = 1;
} else {
list.add(0);
}
for(int i = 1;i < s.length();i++) {
if(s.charAt(i) == '*') {
pre[i] = pre[i - 1] + 1;
} else {
pre[i] = pre[i - 1];
list.add(i);
}
}
for(int i = 0;i < m;i++) {
int st = Collections.binarySearch(list, queries[i][0]);
if(st < 0) {
st = -st - 1;
}
int ed = Collections.binarySearch(list, queries[i][1]);
if(ed < 0) {
ed = -ed - 2;
}
if(st <= ed) {
ans[i] = pre[list.get(ed)] - pre[list.get(st)];
}
}
return ans;
}
}
看了题解后,第一个步骤的优化也可以使用前缀和
class Solution {
public int[] platesBetweenCandles(String s, int[][] queries) {
int m = queries.length;
int n = s.length();
int[] ans = new int[m];
int[] pre = new int[n];
// 该下标最左的一个蜡烛
int[] left = new int[n];
// 该下标最右的一个蜡烛
int[] right = new int[n];
if(s.charAt(0) == '*') {
pre[0] = 1;
left[0] = -1;
} else {
left[0] = 0;
}
for(int i = 1;i < n;i++) {
if(s.charAt(i) == '*') {
pre[i] = pre[i - 1] + 1;
left[i] = left[i - 1];
} else {
pre[i] = pre[i - 1];
left[i] = i;
}
}
if(s.charAt(n - 1) == '*') {
right[n - 1] = -1;
} else {
right[n - 1] = n - 1;
}
for(int i = n - 2;i >= 0;i--) {
if(s.charAt(i) == '*') {
right[i] = right[i + 1];
} else {
right[i] = i;
}
}
for(int i = 0;i < m;i++) {
int st = right[queries[i][0]];
int ed = left[queries[i][1]];
if(st == -1 || ed == -1) {
ans[i] = 0;
} else if(st <= ed) {
ans[i] = pre[ed] - pre[st];
}
}
return ans;
}
}