给定一个长度为p的数组,其中可能包含重复元素,找到包含数组所有元素至少一次的连续最短序列长度
我们可以使用尺取法定义左(left)右(right)两个指针,代表[left,right)为当前有效长度(左闭右开),按照如下思路进行尺取法
- 1、不断的移动right,直到right=p或者[left,right)中包含数组全部元素至少一次
- 2、如果right=p,但是[left,right)仍然不包含全部元素至少一次,退出程序
- 3、记录 result = min (result , res)
- 4、放大left
在获取输入的时候,可以使用set去重,然后set的大小len就是去重后的数量,可以使用map记录每个元素出现的个数,当right右移时,判断如果有元素右移之前是0变成1了,把sum+1,同时不管sun是否变化,都要更新map里的值,然后不断增大right,直到sum==len
当left右移动时,从map中拿到去掉的元素出现的次数,如果去掉之后这个元素出现了0次,那么sum-1,同时不管sum是否变化,一定要更新map
然后每次sum==len时,更新结果为min(result,right-left)
- #include
- #include
- #include
- using namespace std;
- int arr[1000007], n = 0, len = 0, distinctArr[1000007], countArr[1000007], res;
- map<int, int> cntMap;
- void input()
- {
- scanf("%d", &n);
- res = n;
- set<int> distinctSet;
- for (int i = 0; i < n; i++)
- {
- scanf("%d", &arr[i]);
- distinctSet.insert(arr[i]);
- cntMap[arr[i]] = 0;
- }
- len = distinctSet.size();
- }
- void solve()
- {
- // 我们设置[left,right)为有效范围
- int left = 0, right = 0, sum = 0, cnt;
- while (left <= right)
- {
- while (right < n && sum < len)
- {
- cnt = cntMap[arr[right]];
- if (cnt == 0)
- {
- sum++;
- }
- cnt++;
- cntMap[arr[right++]] = cnt;
- }
- if (sum < len)
- {
- return;
- }
- res = min(res, right - left);
- cnt = cntMap[arr[left]];
- cnt--;
- if (cnt == 0)
- {
- sum--;
- }
- cntMap[arr[left++]] = cnt;
- }
- }
- int main()
- {
- input();
- solve();
- printf("%d\n", res);
- return 0;
- }