
背景:本主题主要介绍在解决Leetcode题中的思想和思维模式。本文通过对求众数的题目类型,对具体思路进行介绍。
题目:给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/N ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1(N=2):
输入: [3,2,3]
输出: 3
示例 2(N=3):
输入: [3,3,3,1,1,1,2,2]
输出: [3, 1]
如何解题?
- 目标:找到空间和时间复杂度最优的解法。本题中,时间复杂度最优是O(n),空间复杂度最优是O(1)。
- 根本逻辑:尽量不做无用功。
-
步骤:
-
第一步:写出一些具体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)的判断程序,这样不会造成时间复杂度增加,又可以降低难度。
-
网友评论