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.
给一个非空非负整数的数组,找出和整个数组最大度相同的最短的子数组。度是一个数组里数字出现频率的最大值。
解法:首先要知道整个数组的度,可用哈希表进行统计。度最大的子数组里,首尾数字都是这个度的数字时,子数组是最短的,在用一个哈希表保存,某一个数字第一次出现的index和最后一次出现的index。还要注意度相同的数字可能不只一个所以要求这几个数字中最短的。
Java:
public static class Solution2 { public int findShortestSubArray(int[] nums) { Map<Integer, Integer> count = new HashMap<>(); Map<Integer, Integer> left = new HashMap<>(); Map<Integer, Integer> right = new HashMap<>(); for (int i = 0; i < nums.length; i++) { count.put(nums[i], count.getOrDefault(nums[i], 0) + 1); if (!left.containsKey(nums[i])) { left.put(nums[i], i); } right.put(nums[i], i); } int result = nums.length; int degree = Collections.max(count.values()); for (int num : count.keySet()) { if (count.get(num) == degree) { result = Math.min(result, right.get(num) - left.get(num) + 1); } } return result; } }
Java:
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; }
Python:
class Solution(object): def findShortestSubArray(self, nums): """ :type nums: List[int] :rtype: int """ counts = collections.Counter(nums) left, right = {}, {} for i, num in enumerate(nums): left.setdefault(num, i) right[num] = i degree = max(counts.values()) return min(right[num]-left[num]+1 for num in counts.keys() if counts[num] == degree)
Python: wo
class Solution(object): def findShortestSubArray(self, nums): """ :type nums: List[int] :rtype: int """ if len(nums) < 2: return len(nums) degree = collections.Counter() index = collections.defaultdict(list) max_degree = 0 max_num = [] for k, v in enumerate(nums): degree[v] += 1 if degree[v] > max_degree: max_degree = degree[v] max_num = [] max_num.append(v) elif degree[v] == max_degree: max_num.append(v) index[v].append(k) min_dis = float('inf') for v in max_num: i, j = index[v][0], index[v][-1] min_dis = min(min_dis, j - i + 1) return min_dis
C++:
class Solution { public: int findShortestSubArray(vector<int>& nums) { int n = nums.size(), res = INT_MAX, degree = 0; unordered_map<int, int> m; unordered_map<int, pair<int, int>> pos; for (int i = 0; i < nums.size(); ++i) { if (++m[nums[i]] == 1) { pos[nums[i]] = {i, i}; } else { pos[nums[i]].second = i; } degree = max(degree, m[nums[i]]); } for (auto a : m) { if (degree == a.second) { res = min(res, pos[a.first].second - pos[a.first].first + 1); } } return res; } };
C++:
class Solution { public: int findShortestSubArray(vector<int>& nums) { int n = nums.size(), res = INT_MAX, degree = 0; unordered_map<int, int> m, startIdx; for (int i = 0; i < n; ++i) { ++m[nums[i]]; if (!startIdx.count(nums[i])) startIdx[nums[i]] = i; if (m[nums[i]] == degree) { res = min(res, i - startIdx[nums[i]] + 1); } else if (m[nums[i]] > degree) { res = i - startIdx[nums[i]] + 1; degree = m[nums[i]]; } } return res; } };