Welcome to Subscribe On Youtube

697. Degree of an Array

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: nums = [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: nums = [1,2,2,3,1,4,2]
Output: 6
Explanation: 
The degree is 3 because the element 2 is repeated 3 times.
So [2,2,3,1,4,2] is the shortest subarray, therefore returning 6.

 

Constraints:

  • nums.length will be between 1 and 50,000.
  • nums[i] will be an integer between 0 and 49,999.

Solutions

Solution 1: Hash Table

Traverse the array and use a hash table to record the number of occurrences of each element in the array, as well as the first and last occurrence positions. Then traverse the hash table to obtain the number with the most occurrences of the element (there may be multiple) and the smallest difference between the first and last positions.

Time complexity $O(n)$, space complexity $O(n)$. Where $n$ is the array length.

Solution 2

This implementation uses hash table. It traverses the relevant values and updates its state as each value is processed. A keyed container records values that must be found or updated efficiently. After all required states have been considered, the maintained result is returned.

  • class Solution {
        public int findShortestSubArray(int[] nums) {
            Map<Integer, Integer> cnt = new HashMap<>();
            Map<Integer, Integer> left = new HashMap<>();
            Map<Integer, Integer> right = new HashMap<>();
            int degree = 0;
            for (int i = 0; i < nums.length; ++i) {
                int v = nums[i];
                cnt.put(v, cnt.getOrDefault(v, 0) + 1);
                degree = Math.max(degree, cnt.get(v));
                if (!left.containsKey(v)) {
                    left.put(v, i);
                }
                right.put(v, i);
            }
            int ans = 1000000;
            for (int v : nums) {
                if (cnt.get(v) == degree) {
                    int t = right.get(v) - left.get(v) + 1;
                    if (ans > t) {
                        ans = t;
                    }
                }
            }
            return ans;
        }
    }
    
  • class Solution {
    public:
        int findShortestSubArray(vector<int>& nums) {
            unordered_map<int, int> cnt;
            unordered_map<int, int> left;
            unordered_map<int, int> right;
            int degree = 0;
            for (int i = 0; i < nums.size(); ++i) {
                int v = nums[i];
                degree = max(degree, ++cnt[v]);
                if (!left.count(v)) {
                    left[v] = i;
                }
                right[v] = i;
            }
            int ans = 1e6;
            for (int v : nums) {
                if (cnt[v] == degree) {
                    int t = right[v] - left[v] + 1;
                    if (ans > t) {
                        ans = t;
                    }
                }
            }
            return ans;
        }
    };
    
  • class Solution:
        def findShortestSubArray(self, nums: List[int]) -> int:
            cnt = Counter(nums)
            degree = cnt.most_common()[0][1]
            left, right = {}, {}
            for i, v in enumerate(nums):
                if v not in left:
                    left[v] = i
                right[v] = i
            ans = inf
            for v in nums:
                if cnt[v] == degree:
                    t = right[v] - left[v] + 1
                    if ans > t:
                        ans = t
            return ans
    
    
  • func findShortestSubArray(nums []int) (ans int) {
    	ans = 50000
    	numsMap := make(map[int]int, len(nums))
    	for _, num := range nums {
    		numsMap[num]++
    	}
    	var maxDegree int
    	for _, num := range numsMap {
    		maxDegree = max(num, maxDegree)
    	}
    	degreeNums := getMaxDegreeElem(maxDegree, numsMap)
    	for _, num := range degreeNums {
    		f := findSubArray(num, nums)
    		ans = min(ans, f)
    	}
    	return
    }
    
    func findSubArray(target int, nums []int) int {
    	start := getStartIdx(target, nums)
    	end := getEndIdx(target, nums)
    	return (end - start) + 1
    }
    
    func getStartIdx(target int, nums []int) (start int) {
    	for idx, num := range nums {
    		if num == target {
    			start = idx
    			break
    		}
    	}
    	return start
    }
    
    func getEndIdx(target int, nums []int) (end int) {
    	for i := len(nums) - 1; i > 0; i-- {
    		if nums[i] == target {
    			end = i
    			break
    		}
    	}
    	return
    }
    
    func getMaxDegreeElem(maxDegree int, numsMap map[int]int) []int {
    	var ans []int
    	for key, value := range numsMap {
    		if value == maxDegree {
    			ans = append(ans, key)
    		}
    	}
    	return ans
    }
    
    
    // Solution 2
    func findShortestSubArray(nums []int) (ans int) {
    	ans = 50000
    	numsMap := make(map[int]int, len(nums))
    	for _, num := range nums {
    		numsMap[num]++
    	}
    	var maxDegree int
    	for _, num := range numsMap {
    		maxDegree = max(num, maxDegree)
    	}
    	degreeNums := getMaxDegreeElem(maxDegree, numsMap)
    	for _, num := range degreeNums {
    		f := findSubArray(num, nums)
    		ans = min(ans, f)
    	}
    	return
    }
    
    func findSubArray(target int, nums []int) int {
    	start := getStartIdx(target, nums)
    	end := getEndIdx(target, nums)
    	return (end - start) + 1
    }
    
    func getStartIdx(target int, nums []int) (start int) {
    	for idx, num := range nums {
    		if num == target {
    			start = idx
    			break
    		}
    	}
    	return start
    }
    
    func getEndIdx(target int, nums []int) (end int) {
    	for i := len(nums) - 1; i > 0; i-- {
    		if nums[i] == target {
    			end = i
    			break
    		}
    	}
    	return
    }
    
    func getMaxDegreeElem(maxDegree int, numsMap map[int]int) []int {
    	var ans []int
    	for key, value := range numsMap {
    		if value == maxDegree {
    			ans = append(ans, key)
    		}
    	}
    	return ans
    }
    
    

All Problems

All Solutions