697. 数组的度『简单』
题目来源于力扣(LeetCode)
目录
一、题目
题目相关标签:数组
提示:
nums.length
在1到50,000区间范围内。nums[i]
是一个在0到49,999范围内的整数。
二、解题思路
2.1 哈希表 + 双指针方式
-
定义 map 记录 nums 数组中各元素出现的次数
-
遍历 map,找到出现次数最大值的一个或多个元素,元素存储到 list 列表中
-
遍历 list 列表,对于列表中的元素,通过左右指针方式遍历 nums 数组
-
找到 list 列表中各元素在 nums 数组中的距离,并记录下距离最小的长度
2.2 多个哈希表方式
-
定义三个哈希表,分别用于记录 nums 数组中各元素第一次出现的索引,最后一次出现的索引和出现的次数
-
遍历 nums 数组,记录下各元素第一次出现的索引,最后一次出现的索引和出现的次数
-
操作记录元素出现次数的 map,找到最多的出现次数
-
遍历记录元素出现次数的 map,当 map 值等于最多的出现次数时,获取到第一次出现的索引和最后一次出现的索引,计算两个索引间的距离,记录下距离最小的长度
三、代码实现
3.1 哈希表 + 双指针方式
public static int findShortestSubArray(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
// map 记录各元素出现的次数
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}
List<Integer> list = new ArrayList<>();
int count = 0;
// 遍历 map,找到出现次数最多的元素(可能有多个)
for (Integer i : map.keySet()) {
int j = map.get(i);
if (j < count) {
continue;
}
// 出现较多次数的元素时
if (j > count) {
// 清空 list
list.clear();
// 重新定义最多次数
count = j;
}
list.add(i);
}
// 数组中各元素出现次数小于 2 时,return 1
if (count <= 1) {
return 1;
}
int len = nums.length;
for (Integer i : list) {
int left = 0;
int right = nums.length - 1;
// 双指针查找某元素的左右距离
while (left < right) {
if (nums[left] != i) {
left ++;
}
if (nums[right] != i) {
right --;
}
// 最短的连续子数组长度 = 最后一次出现的索引 - 第一次出现的索引 + 1
if (nums[left] == i && nums[right] == i) {
// 长度取最小的
len = Math.min(len, right - left + 1);
// 结束,开始下一个出现次数相同元素的查找
break;
}
}
}
return len;
}
3.2 多个哈希表方式
public static int findShortestSubArray(int[] nums) {
int ans = nums.length + 1;
// 某个元素第一次出现的索引
Map<Integer, Integer> leftMap = new HashMap<>();
// 某个元素最后一次出现的索引
Map<Integer, Integer> rightMap = new HashMap<>();
// 某个元素出现的次数
Map<Integer, Integer> countMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int j = nums[i];
// 左边索引仅记录一次
if (!leftMap.containsKey(j)) {
leftMap.put(j, i);
}
// 右边索引需要改变
rightMap.put(j, i);
// 出现每次加 1
countMap.put(j, countMap.getOrDefault(j, 0) + 1);
}
// 获取最大的出现次数
int maxCount = Collections.max(countMap.values());
for (Integer i : countMap.keySet()) {
if (countMap.get(i) == maxCount) {
// 最短的连续子数组长度 = 最后一次出现的索引 - 第一次出现的索引 + 1
ans = Math.min(rightMap.get(i) - leftMap.get(i) + 1, ans);
}
}
return ans;
}
四、执行用时
4.1 哈希表 + 双指针方式
4.2 多个哈希表方式
五、部分测试用例
public static void main(String[] args) {
int[] nums = {1, 2, 2, 3, 1}; // output: 2
// int[] nums = {1, 2, 2, 3, 1, 4, 2}; // output: 6
int result = findShortestSubArray(nums);
System.out.println(result);
}