LeetCode算法题-Degree of an Array(Java实现)
这是悦乐书的第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实现)的更多相关文章
- LeetCode算法题-Subdomain Visit Count(Java实现)
这是悦乐书的第320次更新,第341篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第189题(顺位题号是811).像"discuss.leetcode.com& ...
- LeetCode算法题-Letter Case Permutation(Java实现)
这是悦乐书的第315次更新,第336篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第184题(顺位题号是784).给定一个字符串S,将每个字母单独转换为小写或大写以创建另 ...
- LeetCode算法题-Jewels and Stones(Java实现)
这是悦乐书的第313次更新,第334篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第182题(顺位题号是771).字符串J代表珠宝,S代表你拥有的石头.S中的每个字符都是 ...
- LeetCode算法题-Reach a Number(Java实现)
这是悦乐书的第310次更新,第331篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第179题(顺位题号是754).你站在无限数字线的0号位置.在目的地有个target.在 ...
- LeetCode算法题-Shortest Completing Word(Java实现)
这是悦乐书的第309次更新,第330篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第178题(顺位题号是748).从给定的字典单词中查找最小长度单词,其中包含字符串lic ...
- LeetCode算法题-Self Dividing Numbers(Java实现)
这是悦乐书的第305次更新,第324篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第173题(顺位题号是728).自分割数是一个可被其包含的每个数字整除的数字.例如,12 ...
- LeetCode算法题-Find Pivot Index(Java实现)
这是悦乐书的第304次更新,第323篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第172题(顺位题号是724).给定一个整数nums数组,编写一个返回此数组的" ...
- LeetCode算法题-To Lower Case(Java实现)
这是悦乐书的第301次更新,第320篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第169题(顺位题号是709).实现具有字符串参数str的函数ToLowerCase() ...
- LeetCode算法题-Count Binary Substrings(Java实现)
这是悦乐书的第293次更新,第311篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第161题(顺位题号是696).给定一个字符串s,计算具有相同数字0和1的非空且连续子串 ...
随机推荐
- python操作符笔记
1.**两个乘号就是乘方,比如2**4,结果就是2的4次方,结果是16 2.//就是做浮点除法,并舍弃小数部分(注意不是四舍五入) 3.@是python中的修饰符,具体功能我没弄懂.
- nginx~linux下的部署
一些概念 Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄 ...
- 由Nginx的DNS缓存导致的访问404
现象 访问某个URL出现404,而且全站都是404.通过日志查看Nginx的规则也正确,请求被代理到指定位置. 排查 最近针对这个站点没有修改过Nginx配置也没有站点升级.所以应该是其他原因.首先P ...
- leetcode — interleaving-string
/** * Source : https://oj.leetcode.com/problems/interleaving-string/ * * * Given s1, s2, s3, find wh ...
- javascript入门篇(二)
对 象 对象:一组元素的集合 声明方式:字面量方式 var O = { } 构造函数方式:var obj = new object(); 为对象添加新属性,如:o.name = 'jerry' ...
- eclipse svn插件卸载 重新安装 Subclipse卸载安装 The project was not built since its build path is incomplete This client is too old to work with the working copy at
安装插件的原则就是,要按照规则,插件与本地的svn版本要一致, 这样子本地和eclipse上面就可以无缝使用,不会出现问题 1.卸载eclipse svn插件 2,安装新版的svn插件 2.1,下载 ...
- 解决虚拟机连接不上外网,不能互相ping通
0.解决虚拟机连接不上外网,不能互相ping通 直接在linux系统下,编辑修改如下文件: //编辑文件/etc/sysconfig/network-scripts/ifcfg-eth0 [root@ ...
- Qt显示Linux desktop natification气泡提示框
在现代Linux桌面环境上我们时常可以看到类似的消息框: 这些消息框常用在如下场景: 即时聊天软件的新消息 闹钟定时提示 电池电量提示 邮件消息 长耗时操作的完成提示 在freedesktop.org ...
- .NET读取json数据并绑定到对象
需要引用的命名空间: 读取的具体应用: this代表本实体(对象),通过PopulateObject,直接将读取到的json数据与对象进行绑定 Json保存的具体应用: 将对象保存为Json JObj ...
- C#_asp.net mvc 验证码功能的具体实现
@using (Html.BeginForm("Login", "HomePage",FormMethod.Post)) { <h2>登录</ ...