文章目录
1. 题目来源
链接:数组中出现次数超过一半的数字
来源:LeetCode——《剑指-Offer》专项
2. 题目说明
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
- 1 <= 数组长度 <= 50000
3. 题目解析
方法一:多数投票算法+ O ( n ) O(n) O(n)时间复杂度+最优解法
算法思想相当简单,即不同的数两两抵消,超过一半的数字是抵消后剩余的数字,关于这个算法的详细介绍以及相关 OJ
这是博主的总结链接:[杂谈] 7. Majority Vote Algorithm 多数投票算法
参见代码如下:
// 执行用时 :20 ms, 在所有 C++ 提交中击败了82.68%的用户
// 内存消耗 :21.7 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int majorityElement(vector<int> numbers) {
int num = 0, count = 0;
for (int i = 0; i < numbers.size(); i++) {
if (count == 0) num = numbers[i];
if (numbers[i] == num) count++;
else count--;
}
return num;
}
};
稍作改动并验证正确性版本:
// 执行用时 :20 ms, 在所有 C++ 提交中击败了82.68%的用户
// 内存消耗 :21.8 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int majorityElement(vector<int> numbers) {
int n = numbers.size();
if (n == 0)
return 0;
int num = numbers[0], count = 1;
for (int i = 1; i < n; i++) {
if (numbers[i] == num)
count++;
else
count--;
if (count == 0) {
num = numbers[i];
count = 1;
}
}
// 经过上面的操作, 已经找到该数 num 了.
// 下面的操作是为了确认 num 确实是出现次数超过一半.
count = 0;
for (int i = 0; i < n; i++) {
if (numbers[i] == num)
count++;
}
if (count * 2 > n)
return num;
return 0;
}
};
方法二:sort()排序+ O ( l o g n ) O(logn) O(logn)时间复杂度+投机解法
sort()
排序最中间的数字肯定是超过一半的数字,但是 sort()
时间复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn) 颇高。
参见代码如下:
// 执行用时 :24 ms, 在所有 C++ 提交中击败了62.85%的用户
// 内存消耗 :21.3 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() >> 1];
}
};