笔试面试算法经典-找到数组中出现次数大于N/k的数(Java)

题目
给定一个整型数组arr,再给定一个整数k,打印所有出现次数大于 N/K 的数。如果没有这样的数,打印提示信息。
要求
时间复杂度为O(N*K),额外空间复杂度为O(K)。

思路

每次从数组中删除 K 个不同的数,如果某个数的次数大于 N/K ,这个数最后肯定会剩下来,数学证明:假设 X 的次数为 (N/k+1) > N/K ,如果每次删除 k个不同的数最后数组里面剩余的数里面没有 X 那么肯定删除的次数大于等于(N/k+1)>N/K , 那么:K*(N/K+1)>N,不成立因为数组中只有 N 个数不可能删除掉 比 N 还多的数。

注意:删除后剩余的数不一定全是次数大于 N/K 的数,例如:{1,2,3} k=2, 删除后数组中还剩余 3,但是 3 的次数为 1 ,因此还要看剩余的数的次数是不是大于 N/K.

算法过程:大小为 K 的空间,来保存不同的数,当有K个不同的数时,将每个数的次数减 1当 将次数为1的数删除,如果空间中有这个数时,则将这个数的次数加 1 。

下面是数组arr[]={1 ,2 ,3 ,3 ,5 ,2 ,2 ,3 ,3 ,3 ,5 ,6 ,2 ,2 ,2 ,3 , 3}处理的简单过程图:
《笔试面试算法经典-找到数组中出现次数大于N/k的数(Java)》

代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
public class GetKMajor {

    public static void main(String[] args) {
        int arr[]={1,2,3,3,5,2,2,3,3,3,5,6,2,2,2,3,3};
        int k=3;
        getKMajor(arr,k);
    }
    public static void getKMajor(int arr[],int k)
    {
        if(k<2)
        {
            return;
        }
        HashMap<Integer, Integer> hashMap=new HashMap<Integer, Integer>();
        for(int i=0;i<arr.length;i++)
        {
        //hashmap由于保存k个不同的数,当hashmap中有k个不同的数时,则每个数的次数减1,
        //如果某个数的次数为0,则将其从hashmap中删除。
            if(hashMap.containsKey(arr[i]))
            {
            //如果hashmap中存在这个数,则将这个数的次数加1
                hashMap.put(arr[i],hashMap.get(arr[i])+1);

            }
            else {
                if(hashMap.size()==k-1)
                {
                    //如果hashmap中不存在这个数,如此时hashmap中存在k-1个不同的数则将
                    //hashmap中的每个数的次数减1
                    AllminusOne(hashMap);
                }
                else {
                //hashmap中的不同数个数小于k-1,时将该数加入到hashmap中。
                    hashMap.put(arr[i], 1);

                }
            }
        }   
        for(Entry<Integer, Integer> set:hashMap.entrySet())
        {
            Integer key=set.getKey();
            hashMap.put(key, 0);    
            //对hashmap中剩下的每个数先将次数赋值为0,为后面计算每个数的次数是否大于N/K做准备。 
        }
        for(int i=0;i<arr.length;i++)
        {
            if(hashMap.containsKey(arr[i]))
            {
                hashMap.put(arr[i], hashMap.get(arr[i])+1);
            }
        }
        for(Entry<Integer, Integer> set:hashMap.entrySet())
        {
            Integer key=set.getKey();
            Integer value=set.getValue();
            if(value>arr.length/k)
                System.out.println(key);
                //如果某个数的次数大于K/N则将其输出。
        }
    }
    public static void AllminusOne(HashMap<Integer, Integer> hashMap)
    {
    //将hashmap中的每个数的次数减1,将减 1 后次数为0 的从hashmap中删除。
        ArrayList<Integer> removelist=new ArrayList<Integer>();
        for(Entry<Integer, Integer> set:hashMap.entrySet())
        {
            Integer key=set.getKey();
            Integer value=set.getValue();
            if(value==1)
            {
                removelist.add(key);
            }else {             
                hashMap.put(key, value-1);      
            }
        }
        for(Integer removekey:removelist)
        {
            hashMap.remove(removekey);
        }

    }
}
    原文作者:HankingHu
    原文地址: https://blog.csdn.net/u013309870/article/details/69788342
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞