数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组非空,并且一定存在满足条件的数字(即一定有一个数字出现次数超过一半)。
示例:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
这是本题的最佳解法,利用“抵消”思想。
核心思想:
因为题目保证存在,所以不需要额外验证。
#include
int findMost( std::vector< int > nums )
{
// 候选人
int candidate = nums[ 0 ];
// 投票计数器
int count = 1;
for ( int i = 1; i < nums.size(); ++i )
{
if ( nums[ i ] == candidate )
{
// 相同数字,票数加一
count++;
}
else
{
// 不同数字,票数减一
count--;
// 票数归零,更换候选人
if ( count == 0 )
{
candidate = nums[ i ];
count = 1;
}
}
}
// 因为题目保证存在,所以直接返回候选人即可
return candidate;
}
int main()
{
std::vector< int > nums = { 1, 3, 2, 2, 2, 2, 6 };
int count = findMost( nums );
std::cout << count << std::endl;
}
2
遍历数组,使用哈希表记录每个数字出现的次数,最后找到出现次数大于 n/2 的那个数字。
示例代码:
int findMost( std::vector< int >& nums )
{
std::unordered_map< int, int > freq;
for ( int num : nums )
{
freq[ num ]++;
if ( freq[ num ] > nums.size() / 2 )
return num;
}
return -1; // 不会执行到这里(题目保证存在)
}
将数组排序后,中间位置的元素一定是出现次数超过一半的数字(因为其至少占一半+1)。
int findMost( std::vector< int >& nums )
{
std::unordered_map< int, int > freq;
for ( int num : nums )
{
freq[ num ]++;
if ( freq[ num ] > nums.size() / 2 )
return num;
}
return -1; // 不会执行到这里(题目保证存在)
}