Leetcode_Array -- 697. Degree of an Array [easy]

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.

给定一个非空的非负整数数组nums,数组的度被定义为数组中出现频率最高的元素

你的任务是找到一个与nums度相同的、连续的、且长度最小的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.

Solutions:

Python
'''
首先能想到的就是记录nums中元素出现的次数和起始、终止位置,然后计算起始-终止,取最小的值
且数组的度是与其连续子数组的最大度相同的,所以下面的代码就是根据这个思路写出来的
需要强调一下setdefault函数,setdefault有一个特性,即如果键不在字典中,则添加默认值,
如果键已存在默认值,那么再赋给键默认值,键的默认值不会改变,这样就保证了字典存储的元素位置
永远是元素的起始位置它存储元素起始位置,即使有元素重复,也会记录元素的起始位置不会改变,
'''
(1)
class Solution:
    def findShortestSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        first,dict1 = {},{}   #first记录元素出现的其实位置,dict1记录元素出现的次数
        degree,res = 0,0   #degree从0开始,增长到nums的度,res是符合条件的子数组的长度
        for i,num in enumerate(nums):
            first.setdefault(num,i)   
            dict1[num] = dict1.get(num,0) + 1   #统计元素出现的次数
            if dict1[num] > degree:   #由于dict1[num]在变化(增大),所以degree需要更新,且degree要保证取最大
                degree = dict1[num]
                res = i - first[num]+1   #更新子数组长度信息
            elif dict1[num] == degree:   #当度都一样的时候就比较哪个子数组长度最小,返回最小的
                res = min(i-first[num]+1,res)
        return res
     
(2)
'''
这是另外一种解法,其实思路是一样的,只不过它找元素的起始和终止位置的时候有些不同
这个算法是将正序的nums中元素的第一个位置和倒序的nums中元素的第一个位置记下来
然后用数组长度减去这两个位置,就是与nums度相同的子数组的长度
'''
from collections import Counter
class Solution:
    def findShortestSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums: return 0
        c=collections.Counter(nums)
        degree,length=max(c.values()),len(nums)
        if degree==1: return 1
        rnums=list(reversed(nums))
        return length-max(nums.index(num)+rnums.index(num) for (num,count) in c.items() if count==degree)
C++

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        unordered_map<int,int> first,Count;
        int length = nums.size();
        int degree = 0;
        int res = 0;
        for (int i=0;i<length;i++){
            if (first.count(nums[i]) == 0){
                first[nums[i]] = i; 
            }
            Count[nums[i]]++;
            if (Count[nums[i]]>degree){
                degree = Count[nums[i]];
                res = i-first[nums[i]]+1;
            }
            else if(Count[nums[i]] == degree){
                res = min(i-first[nums[i]]+1,res);
            }
        }
        return res;
    }
};

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值