Description:
Given a non-empty array of non-negative integers nums, the degree of
this array is defined as the maximum frequency of any one of its
elements.
Your task is to find the smallest possible length of a (contiguous) subarray of nums, that has the same degree as nums.
Example 1:
Input: [1, 2, 2, 3, 1] Output: 2 Explanation: The input array has a degree of 2 because both elements 1 and 2 appear twice. Of the subarrays that have the same degree: [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2] The shortest length is 2. So return 2.
Example 2:
Input: [1,2,2,3,1,4,2] Output: 6
Note:
nums.length will be between 1 and 50,000. nums[i] will be an integer between 0 and 49,999.
My Solution:
class Solution { public int findShortestSubArray(int[] nums) { Map<Integer,Integer>map = new HashMap<Integer,Integer>(); int len = nums.length; for(int i = 0;i < len;i++){ map.put(nums[i],(map.get(nums[i]) == null)?0:map.get(nums[i])+1); } int maxCount = 0; List<Integer>list = new ArrayList<Integer>(); for(Integer key : map.keySet()){ if(map.get(key) > maxCount){ maxCount = map.get(key); } } for(Integer key : map.keySet()){ if(map.get(key) == maxCount){ list.add(key); } } List<Integer> temp = new ArrayList<Integer>(); for(int i:nums){ temp.add(Integer.valueOf(i)); } int shortest = temp.lastIndexOf(list.get(0)) - temp.indexOf(list.get(0)) + 1; for(int i = 0;i < list.size();i++){ int first = temp.indexOf(list.get(i)); int last = temp.lastIndexOf(list.get(i)); int length = last - first +1; if(length < shortest){ shortest = length; } } return shortest; } }
Better Solution:class Solution { public int findShortestSubArray(int[] nums) { if (nums.length == 0 || nums == null) return 0; Map<Integer, int[]> map = new HashMap<>(); for (int i = 0; i < nums.length; i++){ if (!map.containsKey(nums[i])){ map.put(nums[i], new int[]{1, i, i}); // the first element in array is degree, second is first index of this key, third is last index of this key } else { int[] temp = map.get(nums[i]); temp[0]++; temp[2] = i; } } int degree = Integer.MIN_VALUE, res = Integer.MAX_VALUE; for (int[] value : map.values()){ if (value[0] > degree){ degree = value[0]; res = value[2] - value[1] + 1; } else if (value[0] == degree){ res = Math.min( value[2] - value[1] + 1, res); } } return res; } }
Best Solution: class Solution { public int findShortestSubArray(int[] nums) { if (nums == null || nums.length == 0) return 0; int maxNum = 0; for (int n : nums){ maxNum = Math.max(n, maxNum); } //由于数组的元素都为正整数,因此int[maxNum + 1]的下标可以包含数组中所有元素 //start以nums的元素为下标,保存对应的起始点 int[] start = new int[maxNum + 1]; //end以nums的元素为下标,保存对应的终止点 int[] end = new int[maxNum + 1]; //que以nums的元素为下标,保存对应的次数 int[] que = new int[maxNum + 1]; for (int i = 0; i < nums.length; i++){ //第一次出现nums[i]时,将i存入start,即起始点 if (que[nums[i]] == 0) start[nums[i]] = i; //每次出现同一个nums元素,更新end数组,即终止点 end[nums[i]] = i; //每次出现同一个nums元素,更新que数组,计数 que[nums[i]]++; } int max = 0; //找出最大degree for (int n : que) max = Math.max(max, n); List<Integer> maxNums = new ArrayList<>(); #找出que中拥有最大计数的下标 for (int i = 0; i < que.length; i++){ if (que[i] == max) maxNums.add(i); } int res = nums.length; #遍历maxNums,找出满足degree的最小子集长度 for (int n : maxNums){ int r = end[n] - start[n] + 1; res = Math.min(r, res); } return res; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-09 10:18:51