计算机算法 | LeetCode-求众数思路(169/229)

背景:本主题主要介绍在解决Leetcode题中的思想和思维模式。本文通过对求众数的题目类型,对具体思路进行介绍。


题目:给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/N ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1(N=2):
输入: [3,2,3]
输出: 3

示例 2(N=3):
输入: [3,3,3,1,1,1,2,2]
输出: [3, 1]


如何解题?

  1. 目标:找到空间和时间复杂度最优的解法。本题中,时间复杂度最优是O(n),空间复杂度最优是O(1)。
  2. 根本逻辑:尽量不做无用功。
  3. 步骤:
    • 第一步:写出一些具体cases来进行解法分析。
      具体的,在本题中,可以对N=2的情况,按照题中示例来进行分析。可以看到,目标数字3的数量占比大于n/2。那么,3比任何其他的数字的数量总和加起来要更多。一种思路就是如果将3和其他数字一对一两两进行抵消,剩下的数字一定是3。这样在这个具体的case中,就得到了一个解题的基本逻辑。

    • 第二步:明确什么有用,什么是无用功。
      在本题的解题思路中,有用的信息是两个数字是否相同。而无用的信息是数字所在的位置,所以本题中不应该使用指针的方式来判断数字之间是否相同。直接采用一个dictionary来储存需要判断的数字即可,dictionary的长度应该是N-1.

    • 第三步:循环思考上述解法中是否有可以省略的无用功,优化空间和时间到最佳。

    • 第四步:明确循环具体逻辑,实现程序。
      具体的实现程序如下,以N=3为例:

      # Create dictionary.
      num_dic = {}
      
      # Loop through.
      for num in nums:
          if num in num_dic.keys():
              num_dic[num] += 1
          elif len(num_dic) != 2:
              num_dic[num] = 1
          elif 0 not in num_dic.values():
              for key in num_dic.keys():
                  num_dic[key] -= 1
          else:
              for key, value in num_dic.items():
                  if value == 0:
                      del num_dic[key] 
                      num_dic[num] = 1
                      break
      # Loop through again to find numbers which are satisfying.
      result = []
      for key in num_dic.keys():
          num_dic[key] = 0
      for num in nums:
          if num in num_dic.keys(): 
              num_dic[num] += 1
      for key in num_dic.keys():
          if num_dic[key] * 3 > len(nums):
              result.append(key)
      
      return result
      
    • P.S: 本题中,一次性找出结果的数字较复杂的时候,可以考虑采用后面拼接一个时间复杂度为O(n)的判断程序,这样不会造成时间复杂度增加,又可以降低难度。

你可能感兴趣的:(计算机算法 | LeetCode-求众数思路(169/229))