- 蜡烛之间的盘子 https://leetcode-cn.com/problems/plates-between-candles/
一个字符串,*代表盘子,|代表蜡烛,查询若干次,每次给你两个端点Left和right,查询left和right之间被蜡烛包裹的盘子最大数量。如下图:
我的思路:
1.用前缀和的思想,开一个数组cont记录从0到i的盘子数量。
2. 对于每次查询的两个端点left和right,我直接开两个while循环,找到left右侧最近的蜡烛下标和right左侧最近的蜡烛下标。
3. cont[right左侧最近的蜡烛下标-left右侧最近的蜡烛下标] 就是结果。
结果超时了,卡在了第二步的那两个while循环上,下面是我的代码:
class Solution {
public:
vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
vector<int> ans;
int len=s.size();
int i,j,left,right;
vector<int> cont;
cont.resize(len+1);
for(i=0;i<len;i++){
if(s.at(i)=='*'){
if(i==0){
cont[i]=1;
}else{
cont[i]=cont[i-1]+1;
}
}else{
if(i==0){
cont[i]=0;
}else{
cont[i]=cont[i-1];
}
}
}
for(i=0;i<queries.size();i++){
left=queries[i][0];
right=queries[i][1];
if(left<0||right>=len){
ans.push_back(0);
}else{
while(left<len&&s.at(left)=='*'){
left++;
}
while(right>=0&&s.at(right)=='*'){
right--;
}
if(left<right&&s.at(left)=='|'&&s.at(right)=='|'){
ans.push_back(cont[right]-cont[left]);
}else{
ans.push_back(0);
}
}
}
return ans;
}
};
然后我看了评论区,有一个思路跟我的有点像,但他没有开两个while循环,而是采用了空间换时间的思想,开了两个vector来记录Left右端最近的蜡烛下标和Right左端最近的蜡烛下标。这点我真没想到。
正确代码:
class Solution {
public:
vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
vector<int> ans,Lcandle,Rcandle;
// Lcandle和Rcandle记录 i左侧和右侧最近的蜡烛下标。
int len=s.size();
int i,j,left=-1,right=-1,sum=0;
vector<int> cont;
cont.resize(len);
Lcandle.resize(len);
Rcandle.resize(len);
// 前缀和处理
for(i=0;i<len;i++){
if(s.at(i)=='*'){
sum++;
}else{
left=i;
}
Lcandle[i]=left;
cont[i]=sum;
}
// 找到当前i最右侧的蜡烛下标
for(i=len-1;i>=0;i--){
if(s.at(i)=='|'){
right=i;
}
Rcandle[i]=right;
}
for(i=0;i<queries.size();i++){
left=queries[i][0];
right=queries[i][1];
if(left<0||right>=len){
ans.push_back(0);
}else{
int l=Rcandle[left];
int r=Lcandle[right];
if(l==-1||r==-1||l>=r){
ans.push_back(0);
}else{
ans.push_back(cont[r]-cont[l]);
}
}
}
return ans;
}
};
评论区还有大佬用前缀和+哈希的思想写的,我觉得代码挺简洁的,思路:
1.遍历一遍字符串,统计从0到i的盘子数量
如果当前是蜡烛,则往map里加一个键值对(蜡烛下标,蜡烛下标之前的盘子数量)
2. 对于给定的两个查询端点left和right,在map里找到大于等于left的键值对和小于等于right的键值对,输出这两个值得前缀和差就OK了。
具体看代码:
public int[] platesBetweenCandles(String s, int[][] queries) {
int n = queries.length;
int length = s.length();
int[] ans = new int[n];
//将索引在"|"时的前缀和盘子数加入哈希表中
TreeMap<Integer, Integer> map = new TreeMap<>();
int count = 0;
for (int i = 0; i < length; i++) {
if (s.charAt(i) == '*'){
if (!map.isEmpty()){
count++;
}
} else {
map.put(i, count);
}
}
for (int i = 0; i < n; i++) {
//获取哈希表中最小 >=左边界的索引
Integer left = map.higherKey(queries[i][0] - 1);
//获取哈希表中最大 <=右边界的索引
Integer right = map.lowerKey(queries[i][1] + 1);
if (left == null || right == null || left >= right){
ans[i] = 0;
} else {
ans[i] = map.get(right) - map.get(left);
}
}
return ans;
}
}