题目来源:https://leetcode-cn.com/problems/majority-element/description/
题目描述:
算法描述:对于该题目,可能有些人想到的就是最暴力的穷举,但是时间复杂度为O(n2)。所以我们不用那种方法。我们可以可以使用分治算法实现也可以用摩尔投票法。
第一种.分治算法实现:
分治法是将整个问题化简为一个一个的小问题去解,将数组分成简单的几部分,比如讲一组数分为两部分,第一部分的众数如果等于第二部分的众数,则这个数就是上一层那一组的众数,如果第一部分不等于第二部分,则遍历这一组数,比较第一部分的众数和第二部分的众数哪个出现频率高,频率高的这个数就是这一组数的众数。
代码如下:
class Solution {
public int majorityElement(int[] nums) {
return find(nums, 0, nums.length - 1);
}
public static int find(int[] nums, int begin, int end) {
if (begin == end || begin + 1 == end)
return nums[begin];
else {
//这里主要是为了把数组一分为二(这里就体现了分治算法的思想)
int mid = (begin + end) / 2;
//leftNum就是一个数组中,左半部分的众数
int leftNum = find(nums, begin, mid);
//rightNum就是一个数组中,左半部分的众数
int rightNum = find(nums, mid + 1, end);
// 左右两部分的众数相同 则这个数是当前这个数组的众数
if (leftNum == rightNum) {
return leftNum;
}else {
// 左右两部分的众数不相同 则这两个数都有可能是这部分的众数
// 那么遍历这个数组 看一下哪个数字的出现频率高,频率高的为当前这个数组的众数
int countLeft = 0;
int countRight = 0;
for (int i = begin; i <= end; i++)
if (nums[i] == leftNum)
countLeft++;
else if (nums[i] == rightNum)
countRight++;
if (countLeft > countRight)
return leftNum;
else
return rightNum;
}
}
}
}
第二种.摩尔投票法实现:
摩尔投票法的基本思想很简单,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。那么有没有可能出现最后有两种或两种以上元素呢?根据定义,这是不可能的,因为如果出现这种情况,则代表我们可以继续一轮投票。因此,最终只能是剩下零个或一个元素。
代码如下:
class Solution {
public int majorityElement(int[] nums) {
int result = nums[0], count = 0;
for (int num : nums) {
if (count == 0) {
result = num;
count++;
} else {
if (result == num) {
count++;
} else {
count--;
}
}
}
return result;
}
}