力扣2055. 蜡烛之间的盘子

力扣2055. 蜡烛之间的盘子_第1张图片
力扣2055. 蜡烛之间的盘子_第2张图片
这一题刚开始没有什么思路,只知道因为数据范围是10000,要利用前缀和预处理出来要求的范围内有几个**,但如何找要求的范围内的左边的|和右边的|呢,我的第一个想法是再写一个for循环找出来最左边和最右边的|的位置,很明显的是,这样的时间复杂度是O(n^2)。
看题解才知道:
对找|的最左边和最右边的位置,可以用一个二分来优化这样时间复杂度就降到O(nlogn)是满足题意的
也就是可以把问题简化为在一段范围内,找出大于左边界的最小的|的位置,
找出距离右边界的最小的|的位置。是二分的常见题型。
值得一提的时候在写两个二分的时候还是写错了,借助gpt才写对,说明自己对二分的掌握还是不透彻
具体代码如下:

class Solution {
public:
   vector list;
int sum[100005];
 vector platesBetweenCandles(string s, vector>& queries) {
     vector ans;
     
     for(int i=0;i=pre)
		  	{
		  		premax=list[mid];
		  		r=mid-1;
			}
			else
			{
				l=mid+1;
			}
		} 
	//	cout<

本质上还是好理解的,只要对前缀和,和二分有很强的掌握即可。
第二种方法是裸前缀和,也是我认为这一题重点需要学习的地方,
我们可以把每个位置距离它左边最近的|和右边的最近的|提前找到,然后在枚举queries的时候,直接找左边界的离它最近的右边的|,和右边界的离它最近的左边的|即可。
再借助前缀和直接就可以算出一个范围内的*数量
而在找一个位置的离它左边最近的和右边最近的|可以和前缀和一起预处理。

class Solution {
public:
int sum[100005];
int l[100005];
int r[100005];
 vector platesBetweenCandles(string s, vector>& queries) {
     vector ans;
     int p=-1;
     int q=-1;
     for(int i=0,j=s.size()-1;i=0;i++,j--)
     {
        if(s[i]=='|')
        {
            p=i;
            l[i]=p;
        }
        else
        {
           l[i]=p;
        }
        if(s[j]=='|')
        {
            q=j;
            r[j]=q;
        }
        else
        {
            r[j]=q;
        }
        if(s[i]=='|')
        sum[i+1]=sum[i]+0;
        else
        sum[i+1]=sum[i]+1;
     }

    for(int i=0;i

时间复杂度O(n)。

你可能感兴趣的:(算法,leetcode,算法)