寻找主元素问题

寻找主元素问题,解释一下题目的意思。就是一个集合中的某个数重复出现的次数超过百分之五十。这个数被称为主元素。问题就是找出主元素。

        直观第一想法,两次for循环,依次记录每个值出现多少次,然后找到主元素。这样的时间复杂度是O(n*2)。时间复杂度有点高。

        接着是排序算法,可以根据堆排序或者快排,然后处于二分之一位置的数字就是主元素。这样的只需要堆排序或者快排的时间复杂度,nlog(n)。这样的效率按道理也是不难想到,而且一般是logn对数级别比n2指数级别好多啦。

        再次应该是根据桶排序来查找主元素。但是空间复杂度比较高。会需要M个桶来保存每个数的量。然后再一次n循环,得出最大值的位置。所以一共是O(n+m)。但是这个如果是等差数列为1的数组构成的集合,效率应该是可以接受的。如果是n的集合量不多,任何两数字之间的差距无规律,可以先构造一个映射关系表,讲n的集合根据映射关系,一次映射成等差为1的等差数列。然后再根据桶排序。但是当n量集合很大,而且数字之间的差距无规律的话,那么桶排序浪费的空间略大。有点低效。

        于是引出一个牛逼哄哄时间复杂度O(n)的算法。这个太脑洞大开啦。这个算法的前提:在n集合中,移除两个不相同的数字,剩下数字构成的集合主元素不改变。这个就跟求最大公约数的辗转相除的定理一样,同样脑洞大开。基于问题本身出来的公理推出来的结论,直接用于求解问题本身。太牛逼啦。

上代码:(php版本)

function FindMax($arr)

{

    //如果只有一个数,就是其本身。

    if(count($arr) <=1)

    {

        return $arr[0];

    }

    $key= $arr[0]; //初始化假定主元素

    $mark = 1;      //初始化标记位为1

    //循环arr数组

    for($i=1;$i

    {

        if($mark == 0)

        {

            //标记位退为0的时候,重置初始化条件

           $mark =1;

            $key = $arr[$i];

        }

        if($key == $arr[$i])

        {

            $mark++;    //如果跟假定的初始化主元素相等,将标记位加一

        }

        else

        {

            $mark--;     //如果跟初始化的主元素不相等,则将标记位减一

        }   

    }

    return $key;

}


然后再可以循环依次整个集合数组,依次跟得到的key进行比较,相等就加一,然后得出整个的出现多少次。

运行结果如下:寻找主元素问题_第1张图片

你可能感兴趣的:(寻找主元素问题)