您的位置:首页 > Web前端

剑指offer:数组中出现次数超过一半的数字

2017-08-28 09:11 204 查看
题目:

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

思路1:最直观的想法就是数组排序,然后中间值肯定是要查找的值。 排序最小的时间复杂度(快速排序)O(NlogN),加上遍历。

代码如下:

import java.util.*;

public class Solution {

    public int MoreThanHalfNum_Solution(int [] array) {

        if(array==null||array.length==0){return 0;}//考虑数组为空的时候

        int count=0;

        Arrays.sort(array);//排序

        int num=array[array.length/2];//中位数即是出现次数最多的数字

        for(int i=0;i<array.length;i++){

            if(num==array[i]){//从头开始遍历,和中位数一样的就+1;

                count++;

            }

        }

        if(count<=(array.length/2)){//如果出现次数小于长度一半,即没有这样的数字,返回0

            num=0;

            

        }

           return num;//出现次数大于一半的数字

    }

}

思路2:

出现的次数超过数组长度的一半,表明这个数字出现的次数比其他数出现的次数的总和还多。

考虑每次删除两个不同的数,那么在剩下的数中,出现的次数仍然超过总数的一般,不断重复该过程,排除掉其他的数,最终找到那个出现次数超过一半的数字。这个方法的时间复杂度是O(N),空间复杂度是O(1)。

换个思路,这个可以通过计数实现,而不是真正物理删除。在遍历数组的过程中,保存两个值,一个是数组中数字,一个是出现次数。当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1,如果不同,则次数减1。如果次数为0,则保存下一个数字并把次数设置为1,由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。

代码如下:

import java.util.*;

public class Solution {

    public int MoreThanHalfNum_Solution(int [] array) {

        if(array==null||array.length==0){return 0;}

        int count=0;

        int result;

        result=array[0];

        for(int i=1;i<array.length;i++){

            if(count==0){

                result=array[i];

                count++;

                continue;

            }

            if(result==array[i]){

                count++;

            }else{

                count--;

            }

        }

        count=0;

        for(int j=0;j<array.length;j++){

            if(result==array[j])count++;

        }

        if(count>array.length/2)

            return result;

        return 0;

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  剑指offer