码迷,mamicode.com
首页 > 编程语言 > 详细

剑指Offer对答如流系列 - 数组中出现次数超过一半的数字

时间:2020-01-31 20:36:59      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:array   ==   vat   eth   ret   NPU   int   else   for   

面试题39:数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

问题分析

大家最容易想到的思路是 数字次数超过一半,则说明排序之后数组中间的数字一定就是所求的数字。

既然是数组,要牵扯到排序,大家一般都会选用经典快速排序或者随机快速排序。随机快速排序由于每次划分的依据是从数组随机选出的,所以数据状况对它的影响减弱,时间复杂度为 O(N*logN),而快速排序受数据状况的影响,时间复杂度差的话为O(n^2)。本文使用的是快速排序,书写比较方便。

其实还有一个比较有意思,而且非常好的算法思想,被描述为阵地攻守的思想:

第一个数字作为第一个士兵,守阵地;count = 1;
遇到相同元素,count++;
遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,有可能是主元素。
再加一次循环,记录这个士兵的个数看是否大于数组一般即可。

也就是数字次数超过一半,则说明:该数字出现的次数比其他数字之和还多

遍历数组过程中保存两个值:一个是数组中某一数字,另一个是次数。遍历到下一个数字时,若与保存数字相同,则次数加1,反之减1。若次数=0,则保存下一个数字,次数重新设置为1。由于要找的数字出现的次数比其他数字之和还多,那么要找的数字肯定是最后一次把次数设置为1的数字。

问题解答

思路一(不推荐)

    // 表示输入是否有效
    boolean isInputInvalid = true;
    // 快速排序
    public int MoreThanHalfNum(int [] array) {
        if(array==null ||array.length <= 0) {
            return 0;
        }
        int low=0;
        int high=array.length-1;
        int index=partition(array, low, high);

        while(index != array.length>>1){
            if(index < array.length>>1 ){
                low = index+1;
                index = partition(array,low,high);
            } else {
                high = index-1;
                index=partition(array,low,high);
            }
        }

        //判断次数是否超过一半
        int num=array[index];
        int times=0;
        for(int i=0;i < array.length;i++){
            if(array[i]==num){
                times++;
            }
        }
        if(times*2 > array.length){
            isInputInvalid=false;
            return num;
        }
        return 0;
    }

    private int partition(int[] array,int low ,int high){

        int pivotKey=array[low];
        while(low < high){
            while(low < high &&  array[high] >= pivotKey) {
                high--;
            }
            int temp=array[low];
            array[low]=array[high];
            array[high]=temp;
            while(low < high && array[low] <= pivotKey) {
                low++;
            }
            temp=array[low];
            array[low]=array[high];
            array[high]=temp;
        }
        return low;
    }

思路二(推荐)

    // 表示输入是否有效
    boolean isInputInvalid = true;

    public int MoreThanHalfNum(int [] array) {
        if(array==null || array.length <= 0) {
            return 0;
        }

        int num=array[0];
        int count = 1;
        for(int i=1;i<array.length;i++){
            if(count == 0) {
                num=array[i];
                count++;
            }
            else if(array[i] == num) {
                count++;
            }
            else {
                count--;
            }
        }
        
        if(count > 0){
            int times=0;
            for(int i=0;i<array.length;i++){
                if(array[i] == num){
                    times++;
                }
            }
            if(times*2 > array.length){
                isInputInvalid=false;
                return num;
            }
        }
        return 0;
    }

剑指Offer对答如流系列 - 数组中出现次数超过一半的数字

标签:array   ==   vat   eth   ret   NPU   int   else   for   

原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246441.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!