【LeetCode & 剑指offer刷题】数组题7:39 数组中出现次数超过一半的数字

时间:2021-01-29 11:06:17

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

39 数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
#include <unordered_map> // hash 表实现
using namespace std ;
//方法一:hash 表实现, O n ,O(n)
class Solution
{
public :
    int MoreThanHalfNum_Solution ( vector < int > numbers )
    {
        unordered_map < int , int > counter ;
        int k = numbers . size () / 2 ;
        for ( int ai : numbers ) // 遍历数组 O(n)
        {
            counter [ ai ]++; // 构建计数器
            if ( counter [ ai ] > k ) return ai ; // 节省时间
        }
     //   for(auto& n:counter) // 遍历计数器 O(k) , 这里为 map 中的引用,不是指针,故直接用 n.first
       // {
         //   if(n.second > k)
           // {
          //      return n.first;
         //   }
       // }
        return 0 ; // 不存在
      
    }
};
 
/*
方法二:“消解法”:如果一个数出现次数超过数组的一半,则其出现的次数比其他所有数字出现次数的和还要多,可以用两不同数之间进行消解,最后剩下的数即为出现次数最多那个数
缺点:需要判断是否真的次数超过一半,因为上述条件是必要条件但不是充分条件,时间效率没有hash表法好
O(n),O(1)
 
例:
1 2 2 2 3
i=0,t=0,res =1,t=1
i=1,不等,t-1=0
i=2,res =a[2] =2,t=1
i=3,相等,t+1=2
i=4,不等,t-1=1
*/
class Solution
{
public :
    int MoreThanHalfNum_Solution ( vector < int > numbers )
    {
        int result = numbers [ 0 ];
        int times = 1 ;
       
        for ( int i = 1 ; i < numbers . size (); i ++)
        {
            if ( times == 0 //候选数,
            {
                result = numbers [ i ];
                times = 1 ;
            }
            else if ( numbers [ i ] == result ) times ++; //相等时次数加一,
            else times --; //不等时减一
        }
       
        times = 0 ;
        for ( int ai : numbers )//判断是否真的次数超过一半
        {
            if ( ai == result ) times ++;
        }
        if ( times > numbers . size ()/ 2 ) return result ;
         else   return 0 ; //不存在
       
       
    }
};