先根据DP的想法,我们考虑子问题,设前
i
i
i个元素这样的子串有
F
(
i
)
F(i)
F(i)个,必须以
i
i
i结尾的子串有
f
(
i
)
f(i)
f(i)个
这样有一个很简单的结论:
F
(
i
)
=
F
(
i
−
1
)
+
f
(
i
)
F(i) = F(i-1) + f(i)
F(i)=F(i−1)+f(i)
那么我们的问题的关键就是用
f
(
i
−
1
)
f(i-1)
f(i−1)的知识帮助我们求出
f
(
i
)
f(i)
f(i)了,很显然这两个部分关联性非常强,举个例子比如
A
(
i
)
=
A
(
i
−
1
)
A(i) = A(i-1)
A(i)=A(i−1)的情况,那么有
f
(
i
)
=
f
(
i
−
1
)
f(i) = f(i-1)
f(i)=f(i−1)
这里我们需要一些其它的辅助信息了,首先是两个指针
p
1
(
i
)
p_1(i)
p1(i)和
p
2
(
i
)
p_2(i)
p2(i),我们让他们表示以
i
i
i结尾的可行子串的第一个和最后一个开头位置的索引,不难发现,如果存在以
i
i
i结尾的可行子串,那么所有的
i
i
i结尾可行子串的开头位置应该都在
p
1
(
i
)
p_1(i)
p1(i)和
p
2
(
i
)
p_2(i)
p2(i)之间,而且它们之间的位置作为头也都是可行的,即
f
(
i
)
=
p
2
(
i
)
−
p
1
(
i
)
+
1
f(i) = p_2(i) - p_1(i) + 1
f(i)=p2(i)−p1(i)+1
另外,我们还需要记录一下映射map<int, int>记为
m
i
m_i
mi,他记录以
i
i
i结尾的子串里,包含的数值,以及数值对应出现的位置,要求这个位置是在
i
i
i之前该数值最后一次出现的位置
那么我们接下来就是用
p
1
(
i
)
p_1(i)
p1(i),
p
2
(
i
)
p_2(i)
p2(i)和
m
i
m_i
mi来更新
p
1
(
i
+
1
)
p_1(i+1)
p1(i+1),
p
2
(
i
+
1
)
p_2(i+1)
p2(i+1)和
m
i
+
1
m_{i+1}
mi+1
加入
A
(
i
+
1
)
A(i+1)
A(i+1)出现在了
m
i
m_i
mi中,那么其实
p
1
(
i
)
p_1(i)
p1(i),
p
2
(
i
)
p_2(i)
p2(i)之间的位置做开头一定都可行,只是如果
p
2
(
i
)
=
A
(
i
+
1
)
p_2(i) = A(i+1)
p2(i)=A(i+1)时,我们会有更多可行解;我们首先更新
m
(
A
(
i
+
1
)
)
=
i
+
1
m(A(i+1)) = i+1
m(A(i+1))=i+1并赋值给
m
i
+
1
m_{i+1}
mi+1,需要通过遍历更新
p
2
p_2
p2,我们找到第一个位置
j
j
j,保证
A
(
j
)
=
=
m
i
+
1
(
A
(
j
)
)
A(j) == m_{i+1}(A(j))
A(j)==mi+1(A(j)),领
p
2
(
i
+
1
)
=
j
p_2(i+1)=j
p2(i+1)=j
如果
A
(
i
+
1
)
A(i+1)
A(i+1)未出现在
m
i
m_i
mi中,那么
p
1
(
i
)
p_1(i)
p1(i),
p
2
(
i
)
p_2(i)
p2(i)之间的位置做开头就会多一个元素,不难发现这个元素就是
A
(
p
2
(
i
)
)
A(p_2(i))
A(p2(i)),因此我们令
p
1
(
i
+
1
)
=
p
2
(
i
)
+
1
p_1(i+1) = p_2(i) + 1
p1(i+1)=p2(i)+1,
p
1
(
i
+
1
)
p_1(i+1)
p1(i+1)的更新则和上一个条件分支基本一样,然后更新
m
i
m_i
mi即可
我们可以发现
p
1
p_1
p1和
p
2
p_2
p2的更新都是单调递增的,因此每个位置至多被遍历一次,所以总体复杂度是
O
(
N
)
O(N)
O(N)的
class Solution {
public:intsubarraysWithKDistinct(vector<int>& A,int K){
unordered_map<int,int> mapp;int pre =0, suf =0, now =0;int ans =0;for(; now < A.size(); now++){
mapp[A[now]]= now;if(mapp.size()== K){break;}}for(int i = now; i < A.size(); i++){if(mapp.find(A[i])!= mapp.end()){
mapp[A[i]]= i;while(mapp[A[suf]]!= suf){
suf++;}}else{
mapp.erase(A[suf++]);
mapp[A[i]]= i;
pre = suf;while(mapp[A[suf]]!= suf){
suf++;}}
ans += suf - pre +1;}return ans;}};