【剑指offer】68.数组中出现次数超过一半的数字

总目录:

算法之旅导航目录

 

1.问题描述

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
数据范围:n≤50000,数组中元素的值 0≤val≤10000
要求:空间复杂度:O(1),时间复杂度 O(n)。
保证数组输入非空,且保证有解

 

2.问题分析

 1哈希

因为需要快速查询某元素出现的次数,所以用哈希,需要2次遍历,1次是填充哈希表,1次是找出现次数最大值。

2排序取中间

因为元素数量超过了一般,则排序之后中间元素必然是目标值

3候选法

选某元素作为候选人且计数器+1,与后面的元素展开PK。

如果相同则计数器+1,如果不同则计数器-1,当计数器清零时换一个候选人。

因为目标值超过一般足以PK掉其他候选人,因此最后剩下的候选人即目标值。


3.代码实例

哈希法

 1 class Solution {
 2 public:
 3     int MoreThanHalfNum_Solution(vector<int> numbers) {
 4         unordered_map<int,int> mp;
 5         for (const int val : numbers) mp[val]++;
 6         for (const int val : numbers) {
 7             if (mp[val] > numbers.size() / 2 ) return val;
 8         }
 9         return 0;
10     }
11 };

排序取中

1 class Solution {
2 public:
3     int MoreThanHalfNum_Solution(vector<int> numbers) {
4         sort(numbers.begin(), numbers.end());
5         return numbers[numbers.size() / 2];
6     }
7 };

候选法

class Solution {
  public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int cond = -1;
        int cnt = 0;
        for (int i = 0; i < numbers.size(); ++i) {
            if (cnt == 0) {
                cond = numbers[i];//更换候选人
                cnt = 1; //置信度重置
            } else {
                if (cond == numbers[i]) {
                    cnt++;//置信度+1
                } else {
                    cnt--;//置信度-1
                }
            }
        }

        return cond;
    }
};

 

posted @ 2022-12-05 20:29  啊原来是这样呀  阅读(41)  评论(0)    收藏  举报