467 环绕字符串中唯一的子字符串
题目理解
①S是个“a~z”无限环绕的字符串,参数中也没有显式给出S。
②给定字符串p,寻找s中p的不同子串,即p的子串数目,注意子串,即要求连续。
思路
首先,p的子串怎样在S中找到,要注意到S中的相邻字符有两种情况,一是差值为1,另一种是z和a相邻。
如果p非空,以“bzab”为例,显然p[0]=b一定是一个子串,再接着看p[1]=z,p[1]不满足上述两种情况,则“bz”不是子串,"z"为子串,接着p[2]=a,满足条件,则增加的子串为“a”,“za”,接着p[3]=b,满足条件,增加的子串为“b”,“ab”,“zab”。我们可以发现在连续满足条件的情况下,一个字符增加子串数为1,两个增加数为2,3个为3…,因此我们考虑用pre来记录当前增加的子串数,同时pre也是以当前p[i]为尾的子串数。循环判断,初始pre设置为1(因为单个字符必构成子串),只要满足条件,pre+1,不满足条件,pre重置为1,将所有的pre累加即为结果。
题目中要求的是子串的种类数,上述的pre是所有的子串数,可以使用哈希表记录以p[i]为尾的子串数,例如“bzab”,以z为尾的子串数为1,a为2,b为3,结果即为1+2+3=6.
代码
class Solution {
public:
int findSubstringInWraproundString(string p) {
int n=p.size();
unordered_map<char,int> hash;
int count=0;
int pre=1;
if(n){
hash[p[0]]=pre;
for(int i=1;i<n;i++){
if(p[i]-p[i-1]==1||p[i-1]-p[i]==25)
pre+=1;
else
pre=1;
hash[p[i]]=max(hash[p[i]],pre);
}
for(auto c:hash)
count+=c.second;
}else
return 0;
return count;
}
};
795 区间子数组个数
题目理解
给定数组A,L,R,求的是满足子数组中最大元素满足>=L&&<=R,要注意只要最大元素满足条件即可,且子数组元素要连续。
思路
先考虑如果要求最大元素满足<=R的情况,和上题思路类似,以[2, 1, 4, 3]为例,假设R=4,首先2<4,增加子数组为{2};接着1<4,增加的子数组为{1},{2,1};接着4=4,增加子数组为{4},{1,4},{2,1,4},同理3增加的子数组为{3},{4,3},{1,4,3},{2,1,4,3}。
但这只考虑了最大元素小于等于R的情况,最大元素还要满足大于等于L。因为最大元素满足<=R一定包含最大元素<L的情况(要注意是<),只要将最大元素小于L的子数组从中剔除掉,剩下的就是最大元素大于等于L小于等于R的子数组。
题目中对字数组的判断可能是根据数组索引,因此即使数组元素相同但下标不同也为不同的子数组,例如{2,2}结果为3。
代码
class Solution {
public:
int numSubarrayBoundedMax(vector<int>& A, int L, int R) {
int preL=0,preR=0;
int n=A.size();
int numL=0,numR=0;
for(int i=0;i<n;i++){
if(A[i]<L)
preL+=1;
else preL=0;
numL+=preL;
}
for(int i=0;i<n;i++){
if(A[i]<=R)
preR+=1;
else preR=0;
numR+=preR;
}
return numR-numL;
}
};
904 水果成篮
题目理解
通俗讲,每个篮子只携带一种类型的水果,两个篮子,也就是子数组中只有两种元素,能收集到的水果树的最大总量,也就是,最长子数组。
思路
还是寻找最长连续子数组的问题,不过是加上了只能有两种元素的限定条件。用哈希表来储存当前子数组中的元素数,结果为哈希表的尺寸为2时的最大元素数。
滑动窗口的思想是右指针先递增,也就是增大滑动窗口长度,直到不满足哈希表尺寸为2,在这之前得到的是左指针固定在0位置时的最长子数组,这就是当前右指针之前的最长子数组;接着递增左指针,即缩小滑动窗口长度直到再次满足条件,这是当前右指针的最长子数组,继续循环直到遍历完数组。
代码
class Solution {
public:
int totalFruit(vector<int>& tree) {
int n=tree.size();
int res=0;
unordered_map<int,int> hash;
for(int L=0,R=0;R<n;R++){
hash[tree[R]]++;
while(hash.size()>2){
hash[tree[L]]--;
if(hash[tree[L]]==0)
hash.erase(tree[L]);
L++;
}
res=max(res,R-L+1);
}
return res;
}
};
992 K个不同整数的子数组
题目理解
给定数组A和K,求的是正好有K种整数的子数组。
思路
与795题类似,求出当子数组中的元素种类小于等于K时子数组数,再求出当子数组中的元素种类小于等于K-1时子数组数,即为所求。
代码
class Solution {
public:
int mostK(vector<int>& A, int K)
{
int n=A.size();
int res=0;
unordered_map<int,int> hash;
for(int L=0,R=0;R<n;R++){
++hash[A[R]];
while(hash.size()>K){
--hash[A[L]];
if(hash[A[L]]==0)
hash.erase(A[L]);
++L;
}
res+=R-L+1;
}
return res;
}
int subarraysWithKDistinct(vector<int>& A, int K) {
return mostK(A,K)-mostK(A,K-1);
}
};