数据结构——数组(4)以O(n)时间复杂度,找出数组中出现次数超过一半的数

构建二维数组法:时间和空间复杂度都大,不合题意。
先对数组排序,再取中间元素的方法,最快的排序算法时间复杂度为O(logn),不合题意。
因此,需要采用其他的一些技巧实现。

方法一:由于目标数字,在数组中出现的次数超过一半。那么,若每次都取出其中两个不同的数,最后剩下的必然为出现次数最多的数。
该方法避免排序,且时间复杂度为O(n)。

#include <stdlib.h>
#include<iostream>
using namespace std;
int findMostAppear(int *a,int len)
{
    int candidate=0;//候选点,作为不同数字点对中的参考点
    int count=0;//计数,若被选择的点和参考候选点一样,就+1;不一样,-1;若该计数=0,重新选取候选点
    for(int i=0;i<len;i++)
    {
        //若count为0,说明没有候选点,选择一个候选点
        if(count == 0)
        {
            candidate=a[i];
            count=1;
        }
        //若count不为0,说明有候选点,判断a[i]是否和候选点一样.若一样,count++;若不一样,count--,当count减到0的时候,重新选择候选点
        else
        {
            if(candidate == a[i] )
                count++;
            else
                count--;
        }
    }
    if (count==0)//判断,若最后两两组队,都没有了(偶数组),则不存在超多次数一般的数
        return -1;
    else         //else,存在超过一半的数,且就是最后留下的candidate值
        return candidate;//最后剩的数就是要找的超过一半的数
}
int main()
{
    int array[]={1,1,2,2,3,4,1,1};
    int length=sizeof(array)/sizeof(array[0]);
    int i=findMostAppear(array,length);
    cout<<i<<endl;
    getchar();
}

方法二:Hash法。
首先,构建hash_map,然后,遍历数组,找到出现次数最大的关键字和其对应的最大次数,然后判断该最大次数是否大于等于数组长度的一半,从而确定是否存在次数超过数组一半长度的数。

#include <hash_map>
#include <iostream>
using namespace std;

int findMostAppearHash(int *a,int len,int &val)
{
    hash_map<int,int>myhash;
    for (int i=0;i<len;i++)
    {
        if(     ++myhash[a[i]] >= myhash[val]  )
            val =a[i];
    }

    //判断最大次数是否大于数组长度一半
    int count = myhash[val];
    if (count>=(len+1)/2)
    {
        cout<<"找到超过数组一半的数"<<endl;   
        return val;
    }
    else
        {
            cout<<"不存在超过数组一半的数"<<endl;
        return -1;
    }
}

int main()
{
    int array[]={1,1,2,2,3,4,1,1};
    int length=sizeof(array)/sizeof(array[0]);
    int value=0;
    int i=findMostAppearHash(array,length,value);
    cout<<i<<endl;
    getchar();
}

方法三:使用两个变量A和B。
其中A存储某个数组中的数,B用来计数。开始时候讲B初始化为0,然后遍历数组。
若当前数与A不同,判断:若B=0,则A=当前数; 若B>0,则B=B-1。
若当前数与A相同,B计数加1。
遍历结束,A中存储的数就是所要找的数。该算法时间复杂度为O(n), 空间复杂度为O(1)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章