原题地址(简单)

方法1—哈希表

思路

感觉这题其实可以来个中等难度的。。。
思路就是找出数组的度,然后找出出现次数等于度的那些数,然后再找出这些数的始末位置,看看哪个长度最小,就酱……

代码

开始只想到了用unordered_map存储数和其出现次数,代码写的较为麻烦些。

  1. class Solution {
  2. public:
  3. int findShortestSubArray(vector<int>& nums) {
  4. unordered_map<int, int> um;
  5. for(auto num : nums) um[num]++;
  6. vector<int> v;
  7. int n = nums.size(), ans = n, freq = 0;
  8. for(auto it = um.begin(); it!= um.end(); it++) { // 找出度
  9. if(it->second > freq) freq = it->second;
  10. }
  11. for(auto it = um.begin(); it!= um.end(); it++) { //找出出现次数为度的那些数
  12. if(it->second == freq) v.push_back(it->first);
  13. }
  14. for(int i=0; i<v.size(); i++) { // 寻找这些数的始末位置
  15. int l = 0, r = n - 1;
  16. while(l < n) {
  17. if(nums[l] != v[i])
  18. l++;
  19. else break;
  20. }
  21. while(r >= 0) {
  22. if(nums[r] != v[i])
  23. r--;
  24. else break;
  25. }
  26. ans = min(ans, r - l + 1);
  27. }
  28. return ans;
  29. }
  30. };

后来看了题解,发现如果用unordered_map同时存储数的出现次数以及始末位置,会更快.

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        unordered_map<int, vector<int>> um;
        int n = nums.size(), ans = n, freq = 0;
        for(int i = 0; i < n; i++) {
            if(um.count(nums[i])) {
                um[nums[i]][0]++;
                um[nums[i]][2] = i;
            }
            else {
                um[nums[i]] = {1, i, i};
            }
        }

        for(auto it = um.begin(); it!= um.end(); it++) {
            if(it->second[0] > freq) {
                freq = it->second[0];
                ans = it->second[2] - it->second[1] + 1;
            }
            else if(it->second[0] == freq)
                ans = min(ans, it->second[2] - it->second[1] + 1);
        }

        return ans;
    }
};

时空复杂度

均为O(N)