区间统计查询(预处理+前缀和)
原题在这里。
这题我思路完美,但是在实现的时候被疯狂卡边界问题(大晚上的脑子不清醒,一如既往的空想不打草稿地做题)。
概述题意:给定两种符号"*","|"组成的字符串,要求输出给定(数组)区间内"|"包含的"*"数量和。
输入:s = "**|**|***|", queries = [[2,5],[5,9]]
输出:[2,3]
解释:
- queries[0] 有两个盘子在蜡烛之间。
- queries[1] 有三个盘子在蜡烛之间。
下面是我的思路过程:
analyse:
        1.由于是区间查询,想到树状数组和倍增打表
        2.由于是两个蜡烛之间,所以考虑将直接将蜡烛的下标对标ans处理(前缀和),定义num[i]表示符号"|"的序号数值
            区间[l,r]
            处理成下标对应蜡烛数目,然后边缘收缩(左右边界蜡烛下标x,y)即是答案(y-x-(num[y]-num[x]))
            进一步优化边缘收缩
                将所有的蜡烛存入数组中,直接处理数组,二分搜索,时间复杂度就是线性了
           【这里我就直接开始上手了,然后因为二分搜索被疯狂卡边界】
                [还可以将蜡烛直接处理成边界](预处理)
下面是我前缀和+二分代码:
class Solution { vector<int> vc; int find(int x) { int l = -1, r = vc.size(); while (l + 1 < r) { int mid = (l + r) >> 1; if (vc[mid] <= x) l = mid; else r = mid; } return r; } public: vector<int> platesBetweenCandles(string s, vector<vector<int>> &queries) { int sum = 0, len1 = s.length(), len2 = queries.size(), l, r; vector<int> num(s.length()), ans; for (int i = 0; i < len1; ++i) if (s[i] == '|') num[i] = ++sum, vc.emplace_back(i); for (int i = 0; i < len2; ++i) { l = queries[i][0], r = queries[i][1]; if (vc.size() > 0) { l = vc[min(find(l - 1), (int)vc.size() - 1)]; //第一个区间左侧蜡烛位置 r = vc[max(find(r) - 1, 0)]; //最后一个区间右侧蜡烛位置 } else l = r; ans.emplace_back((r >= l) ? r - l - (num[r] - num[l]) : 0); } return ans; } };
还有一点是,在传形参给函数的时候,如果参数是数组,多次调用函数也会大量消耗不应该的time。
然后是很标准的前缀和+预处理:
class Solution { public: vector<int> platesBetweenCandles(string s, vector<vector<int>> &queries) { int sum = 0, len1 = s.length(), len2 = queries.size(), l, r; vector<int> num(len1), left(len1), right(len1), ans; for (int i = 0, l = len1 - i - 1, r = i; i < len1; ++i) { if (s[i] == '|') num[i] = ++sum, r = i; if (s[len1 - i - 1] == '|') l = i; right[i] = r; //右侧的边界蜡烛下标 left[len1 - i - 1] = l; //左侧边界蜡烛下标 } for (int i = 0; i < len2; ++i) { l = queries[i][0], r = queries[i][1]; l = right[l], r = left[r]; cout << "l==" << l << ", r==" << r << endl; ans.emplace_back((r >= l) ? r - l - (num[r] - num[l]) : 0); } return ans; } };
嗐,至少说分析已经很正确了,题解区也很多我这样的做法,但是还是不够完美。
搜索
复制
                    
                
                
            
        
浙公网安备 33010602011771号