给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:[3,2,3]
输出:3
示例 2:
输入:[2,2,1,1,1,2,2]
输出:2
题解:https://leetcode-cn.com/problems/majority-element/solution/tu-jie-mo-er-tou-piao-fa-python-go-by-jalan/
摩尔投票法(Boyer–Moore majority vote algorithm),也被称作「多数投票法」,算法解决的问题是:如何在任意多的候选人中(选票无序),选出获得票数最多的那个。
算法可以分为两个阶段:
----对抗阶段:分属两个候选人的票数进行两两对抗抵消
-----计数阶段:计算对抗结果中最后留下的候选人票数是否有效
投票法思路
根据上述的算法思想,我们遍历投票数组,将当前票数最多的候选人与其获得的(抵消后)票数分别存储在 major 与 count 中。
当我们遍历下一个选票时,判断当前 count 是否为零:
----若 count == 0,代表当前 major 空缺,直接将当前候选人赋值给 major,并令 count++
----若 count != 0,代表当前 major 的票数未被完全抵消,因此令 count–,即使用当前候选人的票数抵消 major 的票数
详细图解
以 [2,2,1,3,1,2,2] 为例。
遍历数组第一个元素 2 时,因 major 空缺,所以赋值 major = 2,且票数 count = 1:
我们发现第二个元素依旧是「候选人」2,与 major 相同,因此将票数加一:
第三个元素是 1,与 major 不同,因此发生「对抗」,将当前 major 的票数冲抵掉 1 票:
第四个元素是 3,又与 major 不同,因此产生「对抗」,票数继续冲抵:
当遍历到第五个元素 1 时,我们发现当前 count 已经归 0,说明 major 位置空缺,因此我们令 major = 1,且 count = 1:
第六个元素是 2,与 major 不同,因此进行票数抵消,元素 1 刚上位又要下台了:
此时 count 又归零了,因此当遍历到最后一个元素 2 时,令 major = 2,票数 count = 1:
至此遍历结束,求出的多数元素为元素 2。
代码逐步调试:
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
major = 0
count = 0
for n in nums:
print('n:',n)
print('count:', count)
print('原major:', major)
if count == 0:
major = n
print('if后major:', major)
if n == major:
count = count + 1
print('if后count1:', count)
else:
count = count - 1
print('if后count2:', count)
return major
if __name__ == '__main__':
s = Solution()
result_list = s.majorityElement([4,2,2,1,2])
print('result_list:', result_list)
输出为:
n: 4
count: 0
原major: 0
if后major: 4
if后count1: 1
n: 2
count: 1
原major: 4
if后count2: 0
n: 2
count: 0
原major: 4
if后major: 2
if后count1: 1
n: 1
count: 1
原major: 2
if后count2: 0
n: 2
count: 0
原major: 2
if后major: 2
if后count1: 1
result_list: 2
复杂度
时间复杂度:O(n),仅遍历一次数组
空间复杂度:O(1),没有使用额外空间