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

Posted 氵冫丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数组中出现次数超过一半的数字相关的知识,希望对你有一定的参考价值。

题目

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

解题

方法一:快排思想
数组中某个元素出现次数超过数组长度的一半,则数组排序后这个数一定是中位数
但是当不存在这样的数时候就不是中位数了。
用快排的思想解决
只需要找到中间位置的那个数就好了
更进一步的说就是找到中间位置的下标
利用快排每次对数组进行划分,当划分位置在中间位置时候,停止划分
下面对中间位置的这个数检测出现次数就好了

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)
            return 0;
        int left = 0;
        int right = array.length - 1;
        int middle = (right+1)/2;
        int index = partition(array,left,right);
        while(middle != index){
            if(index >middle){
                right = index-1;
                index = partition(array,left,right);
            }else{
                left = index+1;
                index = partition(array,left,right);
            }
        }
        int number = array[middle];
         if(check(array,number,middle)){
             return number;
         }else
             return 0;
    }
    public boolean check(int[] array,int val,int middle){
        int count = 0;
        int i = middle;
        int j = i+1;
        while(i>=0 && array[i] == val){
            i--;
            count++;
        }
        while(j<array.length && array[j] == val){
            j++;
            count++;
        }
        return count*2>=array.length;
    }
    // 划分位置
    public int partition(int [] A,int low ,int high){
        int x = A[high];
        int i = low - 1;
        for( int j = low;j<= high - 1;j++){
            if( A[j] <= x){
                i = i + 1;
                swap(A,i,j);
            }
        }
        i = i + 1;
        swap(A,i,high);
        return i;
    }

    public void swap(int[] array,int i,int j){
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
}   

方法二:找到出现最多的数

遍历数组保存两个值:一个是数字中的一个数,一个是次数。当遍历到下一个数的时候,如果下一个数和之前保存的数相同,则次数加一;如果下一个数与之前保存的数不同,则次数减1.如果次数为0,保存下一个数,并设置次数为1.
由于我们找到的数字出现的次数比其他所有出现的次数之和还要多,那么要找到的数字肯定是最后一次把次数设置为1对应的数字。

public class Solution {
    public int MoreThanHalfNum_Solution(int [] A) {
        if(A == null || A.length == 0)
            return 0;
        int num = A[0];
        int times = 1;
        for(int i = 1;i< A.length ;i++){
            if(A[i] == num){ // 相等次数 + 1
                times++;
            }else{ // 不相等
                if( times>0){ // 次数 -1 
                    times--;
                }else{
                    num = A[i]; // 更新比较数 和 次数
                    times = 1;
                }
            }
        }
        times = 0;
        for(int i = 0;i<A.length;i++){
            if(A[i] == num)
                times++;
        }
        if(times> A.length/2)
            return num;
        return 0;
    }

}

方法三:HashMap
统计次数

import java.util.*;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] A) {
        if(A == null || A.length == 0)
            return 0;
        if(A.length ==1)
            return A[0];
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0;i<A.length;i++){
            if(map.containsKey(A[i])){
                map.put(A[i],map.get(A[i]) +1);
                if(map.get(A[i]) > A.length/2)
                    return A[i];
            }else{
                map.put(A[i],1);
            }
        }
        return 0;
    }
}

以上是关于数组中出现次数超过一半的数字的主要内容,如果未能解决你的问题,请参考以下文章

Java 剑指offer(39) 数组中出现次数超过一半的数字

剑指 Offer 39. 数组中出现次数超过一半的数字 的 详细题解

数组中出现次数超过一半的数字(C语言+Java)

剑指 Offer 39. 数组中出现次数超过一半的数字

出现次数超过一半的数字

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