这是悦乐书的第294次更新,第312篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第162题(顺位题号是697)。给定一个由正整数组成的非空数组,该数组的度数被定义为任意元素出现次数最多的次数。你的任务是找到一个(连续的)nums子数组的最小可能长度,它与nums具有相同的度数。例如:

输入:[1,2,2,3,1]

输出:2

说明:输入数组的度数为2,因为元素1和2都出现两次。在具有相同程度的子阵列中:[1,2,2,3,1],[1,2,2,3],[2,2,3,1],[1,2,2],[2,2,3],[2,2],最短的长度是2.所以返回2。



输入:[1,2,2,3,1,4,2]

输出:6



注意

  • 数组长度将介于1到50,000之间。

  • 数组中的元素是0到49,999之间的整数。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

按照题目的意思,我们需要先把出现次数最多的元素找出来,然后再找到该元素第一次出现和最后一次出现的索引位置之间的距离,如果存在多个相同最多次数的元素,还需要比较他们之间的最小值。

因此,第一步,将数组元素存入HashMap,得到最大次数;第二步,将出现最多次数的单个或多个元素添加进数组;第三步,找到新数组中每位元素出现的起始位置,计算距离长度,取其中的较小者。

public int findShortestSubArray(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
int degree = 0;
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0)+1);
// 比较出现次数,取其中较大者
degree = Math.max(degree, map.get(num));
}
// 将最多出现次数相同的元素放入新的数组
int[] occur = new int[nums.length];
int index = 0;
for (Integer key : map.keySet()) {
if (map.get(key) == degree) {
occur[index++] = key;
}
}
int min = Integer.MAX_VALUE;
// 遍历新数组,算出出现次数最多的元素在nums中的索引之差
for (int i=0; i< index; i++) {
// 使用双指针,一前一后遍历nums,找到该元素的索引之差
int start = 0, end = nums.length-1;
// 申明一个变量,存储索引之差
int len = Integer.MAX_VALUE;;
while (start <= end) {
if (occur[i] == nums[start] && occur[i] == nums[end]) {
len = end - start +1;
break;
} else if (occur[i] == nums[start] && occur[i] != nums[end]){
end--;
} else if(occur[i] != nums[start] && occur[i] == nums[end]) {
start++;
} else {
end--;
start++;
}
}
// 取两者之间的最小值
min = Math.min(min, len);
}
return min;
}

03 第二种解法

我们也可以不使用新数组来存那些出现最多的元素,将HashMap的value类型改为数组即可。依旧使用数组中的元素作为key,value变成了一个包含三个元素的数组,存储次数、首次出现索引、最后一次出现索引,依旧是在第一次循环中就得到degree的值,然后遍历HashMap的value,找到元素索引间隔最小的那个。

public int findShortestSubArray2(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int degree = 0;
// 以nums中的元素为key,以一个含有3个元素的数组为value
// 该数组第一个元素为当前元素出现的次数,第二个元素为其第一次出现的位置,第三个元素为其最后一次出现的位置
Map<Integer,int[]> map = new HashMap<Integer, int[]>();
for (int i=0; i<nums.length; i++) {
if (map.containsKey(nums[i])) {
int[] temp = map.get(nums[i]);
// 更新该元素出现次数
temp[0]++;
// 更新该元素最后一次出现的位置(索引)
temp[2] = i;
} else {
map.put(nums[i], new int[]{1, i, i});
}
// 更新degree,取两者之间较大值
degree = Math.max(degree, map.get(nums[i])[0]);
}
int min = Integer.MAX_VALUE;
for (int[] values : map.values()) {
if (values[0] == degree) {
min = Math.min(min, values[2] - values[1] + 1);
}
}
return min;
}

04 第三种解法

对于第二种解法,我们可以再简化下,只使用一个循环来处理。

public int findShortestSubArray3(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int degree = 0;
int min = Integer.MAX_VALUE;
// 以nums中的元素为key,以一个含有2个元素的数组为value
// 该数组第一个元素为当前元素出现的次数,第二个元素为其最后一次出现的位置
Map<Integer,int[]> map = new HashMap<Integer, int[]>();
for (int i=0; i<nums.length; i++) {
if (!map.containsKey(nums[i])) {
map.put(nums[i], new int[]{0, i});
}
// 出现次数累加
map.get(nums[i])[0]++;
// 对degree进行处理
if (degree < map.get(nums[i])[0]) {
degree = map.get(nums[i])[0];
min = i - map.get(nums[i])[1] + 1;
} else if (degree == map.get(nums[i])[0]) {
min = Math.min(min, i - map.get(nums[i])[1] + 1);
}
}
return min;
}

05 第四种解法

我们也可以使用两个HashMap,而不使用数组。第一个HashMap的value存每个元素出现的次数,第二个HashMap的value存每个元素出现的初始位置索引。

在循环中,每次去比较第一个HashMap的value,如果比degree大,就更新degree的值,同时算出该元素起始索引和结束索引之间的距离;如果和degree相等,就在两者之间取较小值。

public int findShortestSubArray4(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int degree = 0;
int min = Integer.MAX_VALUE;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
for (int i=0; i<nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0)+1);
if (!map2.containsKey(nums[i])) {
map2.put(nums[i], i);
}
if (degree < map.get(nums[i])) {
degree = map.get(nums[i]);
min = i - map2.get(nums[i]) + 1;
} else if (degree == map.get(nums[i])) {
min = Math.min(min, i - map2.get(nums[i]) + 1);
}
}
return min;
}

06 小结

算法专题目前已日更超过四个月,算法题文章162+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode算法题-Degree of an Array(Java实现)的更多相关文章

  1. LeetCode算法题-Subdomain Visit Count(Java实现)

    这是悦乐书的第320次更新,第341篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第189题(顺位题号是811).像"discuss.leetcode.com& ...

  2. LeetCode算法题-Letter Case Permutation(Java实现)

    这是悦乐书的第315次更新,第336篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第184题(顺位题号是784).给定一个字符串S,将每个字母单独转换为小写或大写以创建另 ...

  3. LeetCode算法题-Jewels and Stones(Java实现)

    这是悦乐书的第313次更新,第334篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第182题(顺位题号是771).字符串J代表珠宝,S代表你拥有的石头.S中的每个字符都是 ...

  4. LeetCode算法题-Reach a Number(Java实现)

    这是悦乐书的第310次更新,第331篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第179题(顺位题号是754).你站在无限数字线的0号位置.在目的地有个target.在 ...

  5. LeetCode算法题-Shortest Completing Word(Java实现)

    这是悦乐书的第309次更新,第330篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第178题(顺位题号是748).从给定的字典单词中查找最小长度单词,其中包含字符串lic ...

  6. LeetCode算法题-Self Dividing Numbers(Java实现)

    这是悦乐书的第305次更新,第324篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第173题(顺位题号是728).自分割数是一个可被其包含的每个数字整除的数字.例如,12 ...

  7. LeetCode算法题-Find Pivot Index(Java实现)

    这是悦乐书的第304次更新,第323篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第172题(顺位题号是724).给定一个整数nums数组,编写一个返回此数组的" ...

  8. LeetCode算法题-To Lower Case(Java实现)

    这是悦乐书的第301次更新,第320篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第169题(顺位题号是709).实现具有字符串参数str的函数ToLowerCase() ...

  9. LeetCode算法题-Count Binary Substrings(Java实现)

    这是悦乐书的第293次更新,第311篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第161题(顺位题号是696).给定一个字符串s,计算具有相同数字0和1的非空且连续子串 ...

随机推荐

  1. asp.net core系列 24 EF模型配置(主键,生成值,最大长度,并发标记)

    一.主键 键用作每个实体实例的主要唯一标识符. 使用关系数据库时,这会映射到主键的概念. 还可以配置不是主键的唯一标识符.按照约定,名为 Id 或 <type name>Id 的属性会配置 ...

  2. Python爬虫入门教程 34-100 掘金网全站用户爬虫 scrapy

    爬前叨叨 已经编写了33篇爬虫文章了,如果你按着一个个的实现,你的爬虫技术已经入门,从今天开始慢慢的就要写一些有分析价值的数据了,今天我选了一个<掘金网>,我们去爬取一下他的全站用户数据. ...

  3. 精读《正则 ES2018》

    1. 引言 本周精读的文章是 regexp-features-regular-expressions. 这篇文章介绍了 ES2018 正则支持的几个重要特性: Lookbehind assertion ...

  4. Linux - CentOS 登陆密码找回解决方法

  5. leetcode — reverse-linked-list

    /** * Source : https://leetcode.com/problems/reverse-linked-list/ * * * Reverse a singly linked list ...

  6. [三]基础数据类型之Integer详解

        Integer 基本数据类型int  的包装类 Integer 类型的对象包含一个 int 类型的字段     属性简介 值为 2^31-1 的常量,它表示 int 类型能够表示的最大值 @N ...

  7. java continue break 关键字 详解 区别 用法 标记 标签 使用 示例 联系

    本文关键词: java continue break 关键字 详解 区别  用法 标记  标签 使用 示例 联系   跳出循环 带标签的continue和break 嵌套循环  深入continue ...

  8. springboot情操陶冶-web配置(五)

    本文讲讲mvc的异常处理机制,方便查阅以及编写合理的异常响应方式 入口例子 很简单,根据之前的文章,我们只需要复写WebMvcConfigurer接口的异常添加方法即可,如下 1.创建简单的异常处理类 ...

  9. Django 系列博客(十)

    Django 系列博客(十) 前言 本篇博客介绍在 Django 中如何对数据库进行增删查改,主要为对单表进行操作. ORM简介 查询数据层次图解:如果操作 mysql,ORM 是在 pymysql ...

  10. Uncaught SyntaxError: Invalid shorthand property initializer报错

    出现这个错误一定是:把":"写成了"="号