0
点赞
收藏
分享

微信扫一扫

2055.蜡烛之间的盘子

zmhc 2022-03-12 阅读 24

题目

2055.蜡烛之间的盘子

题目大意

给你一个长桌子,桌子上盘子和蜡烛排成一列。给你一个下标从 0 开始的字符串 s ,它只包含字符 '*''|' ,其中 '*' 表示一个 盘子'|' 表示一支 蜡烛

同时给你一个下标从 0 开始的二维整数数组 queries ,其中 queries[i] = [lefti, righti] 表示 子字符串 s[lefti...righti]包含左右端点的字符)。对于每个查询,你需要找到 子字符串中两支蜡烛之间 的盘子的 数目 。如果一个盘子在 子字符串中 左边和右边 至少有一支蜡烛,那么这个盘子满足在 两支蜡烛之间

  • 比方说,s = "||**||**|*" ,查询 [3, 8] ,表示的是子字符串 "*||***\**\***|" 。子字符串中在两支蜡烛之间的盘子数目为 2 ,子字符串中右边两个盘子在它们左边和右边 至少有一支蜡烛。

请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。

样例

image-20220308145028716

数据规模

image-20220308145035202

思路

对于一个区间 [ L , R ] [L,R] [L,R],考虑有多少个盘子位于蜡烛之间。

可以抽象问题:认为蜡烛值 0 0 0,盘子值为 1 1 1,那么就是问区间 [ L , R ] [L,R] [L,R]之间最左端的 0 0 0和最右端的 0 0 0之间有多少个 1 1 1

举例:对于数字1111010101111101111,假设第一个 1 1 1的下标为 0 0 0,那么第一个 0 0 0的下标为 4 4 4,即最左边的 0 0 0(蜡烛)的下标为 4 4 4;最后一个 0 0 0的下标为 14 14 14,即最右边的 0 0 0(蜡烛)的下标为 14 14 14。原问题是求 [ 0 , 18 ] [0,18] [0,18]之间有多少个盘子位于蜡烛之间,现在问题变成了区间 [ 4 , 14 ] [4,14] [4,14]之间有多少个 1 1 1,那么该问题就抽象为了一维前缀和。

那么对于一个区间 [ L , R ] [L,R] [L,R]:如何找到 L L L右边的第一个蜡烛,又如何找到 R R R左边的第一个蜡烛?

  • 定义一个数组l,该数组l[i]用于求解i左边的第一个蜡烛,如果左边没有蜡烛就设定为 − 1 -1 1
  • 定义一个数组r,该数组r[i]用于求解i右边的第一个蜡烛,如果右边没有蜡烛就设定为 − 1 -1 1
  • 定义一个数组sum,该数组sum[i]用于求解区间 [ 0 , i ] [0,i] [0,i]之间 1 1 1的个数

对于每一个查询queries[i],首先取出区间 [ L , R ] [L,R] [L,R],找到 L L L右边的第一个蜡烛r[L],再找到 R R R左边的第一个蜡烛l[R],那么必须保证r[L]!=-1&&l[R]!=-1&&r[L]<l[R],在该条件下答案为sum[l[R]]-sum[r[L]-1]否则答案就是 0 0 0

代码

class Solution {
public:
    vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
        int n=s.length();
		vector<int>sum(n),l(n),r(n);
		for(int i=0,q=0,lmin=-1;i<n;i++){
			if(s[i]=='*'){
				q++;
			}
			if(s[i]=='|'){
				lmin=i;
			}
			sum[i]=q;
			l[i]=lmin;
		}
		for(int i=n-1,rmax=-1;i>=0;i--){
			if(s[i]=='|'){
				rmax=i;
			}
			r[i]=rmax;
		}
		vector<int>ans;
		for(int i=0;i<queries.size();i++){
			int L=queries[i][0],R=queries[i][1];
			ans.push_back(((r[L]==-1||l[R]==-1||r[L]>=l[R])?0:sum[l[R]]-sum[r[L]]));
		}
		return ans;
    }
};

举报

相关推荐

0 条评论