697. 数组的度『简单』

题目来源于力扣(LeetCode

一、题目

697. 数组的度

题目相关标签:数组

提示:

  • nums.length 在1到50,000区间范围内。
  • nums[i] 是一个在0到49,999范围内的整数。

二、解题思路

2.1 哈希表 + 双指针方式

  1. 定义 map 记录 nums 数组中各元素出现的次数

  2. 遍历 map,找到出现次数最大值的一个或多个元素,元素存储到 list 列表中

  3. 遍历 list 列表,对于列表中的元素,通过左右指针方式遍历 nums 数组

  4. 找到 list 列表中各元素在 nums 数组中的距离,并记录下距离最小的长度

2.2 多个哈希表方式

  1. 定义三个哈希表,分别用于记录 nums 数组中各元素第一次出现的索引,最后一次出现的索引和出现的次数

  2. 遍历 nums 数组,记录下各元素第一次出现的索引,最后一次出现的索引和出现的次数

  3. 操作记录元素出现次数的 map,找到最多的出现次数

  4. 遍历记录元素出现次数的 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);
}
posted @ 2020-06-11 21:26  知音12138  阅读(160)  评论(0编辑  收藏  举报