题意:
给定一个长度为n的数列, 找出1-k的连续组合排列个数
思路:
本题可使用双指针维护一个长度为k的滑动区间, 在区间内判断当前区间是否符合要求.
具体如何判断?
这里运用了哈希表及统计量"不同元素个数"来判断.
每次滑动后, 将退出元素哈希值自减, 加入元素哈希值自增, 然后根据它们的哈希值更新"不同元素个数". 区间内 "不同元素个数"==k 则该区间符合要求.
或者运用c++中stl:set的特性(目前还没学会)
错误原因:
首先呢也是读错了题, 没注意到是排列, 即乱序的1-k也是符合要求的, 于是写了个错的暴力
快结束时才发现思路错了, 哎呀.
然后也是写的哈希表来判断, 不过用的遍历, 超时了...
输入:
n,k
n个正整数ai
输出:
一个整数,代表长度为k的连续子数组是排列的数量
AC代码:
#include <bits/stdc++.h>
using namespace std;
int num[100005], hash1[100005] = {0, 0};
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
//双指针划分滑动区间, 用不同数字个数和哈希表维护区间状态, 区间挪动时进行更新
int sum = 0;
int differ = 0;
for (int i = 0; i < k; i++) //维护第一个区间
{
if (hash1[num[i]] == 0)//塞入元素
{
differ++;
}
hash1[num[i]]++;
}
if (differ == k)//判断是否合法
sum++;
for (int i = 1, j = k; i <= n - k && j < n; i++, j++)
{
//每次滑动到后一个区间
hash1[num[i - 1]]--; //踢掉前一个
if (hash1[num[i - 1]] == 0)
{
differ--;
}
if (hash1[num[j]] == 0)//加入后一个
{
differ++;
}
hash1[num[j]]++;
if (differ == k)//判断是否合法
sum++;
}
cout << sum;
return 0;
}