作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/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:

  1. Input: [1, 2, 2, 3, 1]
  2. Output: 2
  3. Explanation:
  4. The input array has a degree of 2 because both elements 1 and 2 appear twice.
  5. Of the subarrays that have the same degree:
  6. [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
  7. The shortest length is 2. So return 2.

Example 2:

  1. Input: [1,2,2,3,1,4,2]
  2. Output: 6

Note:

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

题目大意

数组的度是出现次数最多的数字的出现次数。求一个最短子数组的长度,其度等于数组的度。

解题方法

求出最短相同子数组度的长度

题目大意:

给定非空非负整数数组,数组的度是指元素的最大出现次数。

寻找最大连续区间,使得区间的度与原数组的度相同。

想法很粗暴,直接求出整个数组的degree,然后找出所有的度等于该degree的数,找出最小度的数。

  1. import collections
  2. class Solution(object):
  3. def findShortestSubArray(self, nums):
  4. """
  5. :type nums: List[int]
  6. :rtype: int
  7. """
  8. if len(nums) == len(set(nums)):
  9. return 1
  10. counter = collections.Counter(nums)
  11. degree_num = counter.most_common(1)[0]
  12. most_numbers = [num for num in counter if counter[num] == degree_num[1]]
  13. scale = 100000000
  14. for most_number in most_numbers:
  15. appear = [i for i,num in enumerate(nums) if num == most_number]
  16. appear_scale = max(appear) - min(appear) + 1
  17. if appear_scale < scale:
  18. scale = appear_scale
  19. return scale

上面使用了Counter,下面的直接数,速度有一点提高。

  1. import collections
  2. class Solution(object):
  3. def findShortestSubArray(self, nums):
  4. """
  5. :type nums: List[int]
  6. :rtype: int
  7. """
  8. nums_set = set(nums)
  9. if len(nums) == len(nums_set):
  10. return 1
  11. degree = max([nums.count(num) for num in nums_set])
  12. most_numbers = [num for num in nums_set if nums.count(num) == degree]
  13. scale = 100000000
  14. for most_number in most_numbers:
  15. appear = [i for i,num in enumerate(nums) if num == most_number]
  16. appear_scale = max(appear) - min(appear) + 1
  17. if appear_scale < scale:
  18. scale = appear_scale
  19. return scale

上面的不够快是因为重复计算了多次的nums.count(num),避免重复计算可以使用字典进行保存。这个方法超出了96.7%的提交。

  1. import collections
  2. class Solution(object):
  3. def findShortestSubArray(self, nums):
  4. """
  5. :type nums: List[int]
  6. :rtype: int
  7. """
  8. nums_set = set(nums)
  9. if len(nums) == len(nums_set):
  10. return 1
  11. num_dict = {num:nums.count(num) for num in nums_set}
  12. degree = max(num_dict.values())
  13. most_numbers = [num for num in nums_set if num_dict[num] == degree]
  14. scale = 100000000
  15. for most_number in most_numbers:
  16. appear = [i for i,num in enumerate(nums) if num == most_number]
  17. appear_scale = max(appear) - min(appear) + 1
  18. if appear_scale < scale:
  19. scale = appear_scale
  20. return scale

还能更快吗?可以。把能压缩的列表表达式拆开,这样迭代一次就可以了。最后用了个提前终止,如果scale==degree说明这段子列表里没有其他元素了,一定是最短的。

这个方法超过了99.91%的提交。

  1. import collections
  2. class Solution(object):
  3. def findShortestSubArray(self, nums):
  4. """
  5. :type nums: List[int]
  6. :rtype: int
  7. """
  8. nums_set = set(nums)
  9. if len(nums) == len(nums_set):
  10. return 1
  11. num_dict = {}
  12. degree = -1
  13. for num in nums_set:
  14. _count = nums.count(num)
  15. num_dict[num] = _count
  16. if _count > degree:
  17. degree = _count
  18. most_numbers = [num for num in nums_set if num_dict[num] == degree]
  19. scale = 100000000
  20. for most_number in most_numbers:
  21. _min = nums.index(most_number)
  22. for i in xrange(len(nums)-1, -1, -1):
  23. if nums[i] == most_number:
  24. _max = i
  25. break
  26. appear_scale = _max - _min + 1
  27. if appear_scale < scale:
  28. scale = appear_scale
  29. if scale == degree:
  30. break
  31. return scale

使用堆求最大次数和最小长度

二刷的时候,想到其实同时优化两个指标:最大次数和最小长度。所以,直接遍历所有的数字,同时统计它的次数,起始位置和结束位置,然后用一个堆,进行最大次数和最小长度的选择,对应的长度就是最小长度。

  1. class Solution:
  2. def findShortestSubArray(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: int
  6. """
  7. count = collections.defaultdict(tuple)
  8. for i, num in enumerate(nums):
  9. if num not in count:
  10. count[num] = (1, i, i)
  11. else:
  12. count[num] = (count[num][0] + 1, count[num][1], i)
  13. heap = [(-times, end - start + 1) for times, start, end in count.values()]
  14. heapq.heapify(heap)
  15. return heapq.heappop(heap)[1]

保存最左边出现位置和最右边出现位置

使用两个字典,保存每个数字出现的最左边和最右边位置,这样的话,我们找到了出现次数等于数组的度的数字,然后看它的长度是不是最小的即可。

  1. class Solution:
  2. def findShortestSubArray(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: int
  6. """
  7. left, right = dict(), dict()
  8. count = collections.defaultdict(int)
  9. for i, num in enumerate(nums):
  10. if num not in left:
  11. left[num] = i
  12. right[num] = i
  13. count[num] += 1
  14. degree = max(count.values())
  15. res = float("inf")
  16. for num, c in count.items():
  17. if c == degree:
  18. res = min(res, right[num] - left[num] + 1)
  19. return res

日期

2018 年 1 月 23 日
2018 年 11 月 16 日 —— 又到周五了!

【LeetCode】697. Degree of an Array 解题报告(Python)的更多相关文章

  1. 【LeetCode】697. Degree of an Array 解题报告

    [LeetCode]697. Degree of an Array 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/degree- ...

  2. LeetCode 697. Degree of an Array (数组的度)

    Given a non-empty array of non-negative integers nums, the degree of this array is defined as the ma ...

  3. LeetCode: Search in Rotated Sorted Array 解题报告

    Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you before ...

  4. [LeetCode] 697. Degree of an Array 数组的度

    Given a non-empty array of non-negative integers nums, the degree of this array is defined as the ma ...

  5. leetcode 697. Degree of an Array

    题目: Given a non-empty array of non-negative integers nums, the degree of this array is defined as th ...

  6. 【LeetCode】26. Remove Duplicates from Sorted Array 解题报告(Python&C++&Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 日期 [LeetCode] https:// ...

  7. 【LeetCode】912. Sort an Array 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 库函数排序 桶排序 红黑树排序 归并排序 快速排序 ...

  8. 【LeetCode】941. Valid Mountain Array 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  9. 【LeetCode】88. Merge Sorted Array 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 新建数组 日期 题目地址:https://leetc ...

随机推荐

  1. phpexcel 另存Excel文件方式

    $w = new PHPExcel_Writer_Excel5($e); $dir = 'path/title.xls'; $w->save($dir);

  2. 『学了就忘』Linux文件系统管理 — 63、磁盘配额介绍

    目录 1.磁盘配额概念 2.磁盘配额条件 3.磁盘配额的相关概念 4.磁盘配额实践规划 1.磁盘配额概念 磁盘配额是限制用户或者用户组在一个分区上可以使用的空间大小和文件个数的限制. 扩展: 管理员可 ...

  3. C语言之内核中的struct list_head 结构体

    以下地址文章解释很好 http://blog.chinaunix.net/uid-27122224-id-3277511.html 对下面的结构体分析 1 struct person 2 { 3 in ...

  4. 学习java 7.17

    学习内容: 计算机网络 网络编程 网络编程三要素 IP地址 端口 协议 两类IP地址 IP常用命令: ipconfig 查看本机IP地址 ping IP地址 检查网络是否连通 特殊IP地址: 127. ...

  5. 商业爬虫学习笔记day1

    day1 一. HTTP 1.介绍: https://www.cnblogs.com/vamei/archive/2013/05/11/3069788.html http://blog.csdn.ne ...

  6. vi查找替换命令详解 (转载)

    转载至:   http://blog.csdn.net/lanxinju/article/details/5731843 一.查找 查找命令 /pattern<Enter> :向下查找pa ...

  7. midi的一些概念,包括一些音乐的概念

    参考:http://www.yueqixuexi.com/jita/20180918205363.html https://blog.csdn.net/meicheng777/article/deta ...

  8. Vector Bin Packing 华为讲座笔记

    Vector bin packing:first fit / best fit / grasp 成本:性价比 (先验) 设计评价函数: evaluation function:cosine simil ...

  9. java多线程4:volatile关键字

    上文说到了 synchronized,那么就不得不说下 volatile关键字了,它们两者经常协同处理多线程的安全问题. volatile保证可见性 那么volatile的作用是什么呢? 在jvm运行 ...

  10. Svelte入门——Web Components实现跨框架组件复用(二)

    在上节中,我们一起了解了如何使用Svelte封装Web Component,从而实现在不同页面间使用电子表格组件. Svelte封装组件跨框架复用,带来的好处也十分明显: 1.使用框架开发,更容易维护 ...