华为OD题目:优雅数组
知识点双指针数组Q滑窗
时间限制: 1s 空间限制: 256MB 限定语言: 不限
题目描述:
如果一个数组中出现次数最多的元素出现大于等于k次,被称为k-优雅数组,k也可以被称为 优雅闻值
例如,数组“1,2,3,1,2,3,1J,它是一个3-优雅数组,因为元素1出现次数大于等于3次,数组1,2,3,1,2]就不是一个3-优雅数组,因为其中出现次数最多的元素时~1和2,只出现了2次。
给定一个数组A和k,请求出A有多少子数组是k-优雅子数组~。
子数组是数组中一个或多个连续元素组成的数组。
例如,数组[1,2, 3,4包含10个子数组,分别是:[1],[1,2],[1,2, 3],[1,2,3,4,[2],[2,3].
[2, 3, 4],[3],[3, 4],[4]。
输入描述:
第一行输入两个整数n和k,n是数组A的长度,k是优雅闻值.
第二行输入n个整数,表示给定的数组A。
1 <= n <= 10000.1 <= k <= n
数组A中的元素AW满足: 1 <= AW <= n
输出描述:
数据一个整数,表示数组A中~k-优雅子数组的数量行尾不要有多余空格
示例1
输入:
7 3
1 2 3 1 2 3 1
输出:
1
说明:
只有子数组[1,2,31,2,3,1]是“3-优雅数组
示例2
输入:
7 2
1 2 3 1 2 3 1
输出:
10
说明:
10个优雅子数组分别是 (下标从0计数) :
长度为4: [1,2,3,11(下标03),2,3,1,2(下标14),13,12.31(下标2~5),[1,2. 3.11下标3~6)长度为5: 1,2,3,1,2,2,3,1,2,3,[3,1,2,3,11(下标2~6)
长度为6: [1.2.3.1.2.31(下标05),[2.3,1.2.3.11(下标16)
长度为7: 1,2,3,1,2,3,1
输入:
9 3
9 5 2 1 2 3 1 1 2
输出:
8
解题思路:
- 本题比较巧妙,暴力解法通过率比较低
- 本题比较巧妙,得记一下
- 1: 最开始移动右指针,直到窗口里能有子数组满足K个值相同,那么所有能覆盖此子数组的所有的子数组都满足
- 2:将左指针移动到刚好满足此数组达到K个值相同的最小子数组,
- 可以得出 能够覆盖此最小子数组的所有个数是 (nums.length-right) * (left-preRight);
- 其中 preRight记录上一次right指针的位置,为了方便计算,初始值设置为-1
- 这个要多在纸上画图计算
public class My {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] strings = str.split(" ");
int n = Integer.parseInt(strings[0]);
int k = Integer.parseInt(strings[1]);
String line = sc.nextLine();
String[] split = line.split(" ");
int[] nums = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
//左指针
int i = 0;
int res = 0;
Map<Integer, Integer> map = new HashMap<>();
// 记录上一次r位置,为了方便计算,初始值设置为-1
int preLeft = -1;
for (int j = 0; j < nums.length; j++) {
int val = nums[j];
//指针到这时,窗口里val 的个数
int sameNum = map.getOrDefault(val, 0) + 1;
map.put(val, sameNum);
//如果相同的个数>=k,那么所有能够覆盖此数组的都满足条件
if (sameNum == k) {
//不断的移动左指针,指针指向与有指针指向的值相同
while (i < j) {
if (nums[i] == nums[j]) {
break;
}
// 左指针l移动过程中删除窗口外记录
map.put(nums[i], map.get(nums[i] - 1));
i++;
}
//算出还未统计的,且能覆盖此子数组的所有子数组个数(nums.length-j) * (i-preRight)
res += (nums.length-j) * (i-preLeft);
// 记录左指针
preLeft = i;
// 移除左指针元素
map.put(val, map.get(val) - 1);
i++;
}
}
System.out.println(res);
}
}