Just do it
专注做自己的事,有想做的事就去做好了

分析题目

经典做法是通过Map遍历数组存储每个元素,key是遍历的元素,value是元素出现的次数,最后通过遍历这个Map得到出现K次的数值。

但是上述的方法的时间复杂度是O(n),不符合我们的要求,一般这个时候我们可以从Int类型的数字特性下手,Int类型的数字二进制长度是32位,且一个数字出现K次,其他数都出现M次,且K小于M,如果我们用一个32位的数组,遍历题目给出的数组,将每个元素转为32位二进制,每位的0或1的数值依次存入我们构建的32位的数组中,遇到1则做‘++’操作,最后我们的32位数组中每个元素的值要么是M的整数倍,要么取余的结果就是K的值。当取余接口不等于M是,就说明出现K次的数值在该位上的值就是1。

题解:

    public static int seekKthNum(int[] array,int k, int m){
        // 构建临时的32位数组
        int[] tmp = new int[32];
        // 用于返回的ans
        int ans = 0;
        for (int value : array) {
            // 将value右移i位,与1相与:value的第i位上如果是1,那么&1等于1
            for (int i = 0; i < 32; i++) {
                // tmp[i] 初始默认值是0,因为右边的结果不是1就是0
                tmp[i] += (value >> i) & 1;
            }
        }

        for (int i = 0; i < tmp.length; i++) {
            if(tmp[i] % m == 0){
                continue;
            }
            // 第i位上不是m的整数倍,那么该位上的1一定有出现K次数的值的一份
            if(tmp[i] % m == k ){
                // 将1左移i位,ans做或操作,ans默认是0,或操作与1则1,所以最终的值就是出现K次的值
                ans |= 1 << i;
            }else {
                return -1;
            }
        }
        return ans;
    }

 

posted on 2025-02-22 21:34  Ireck  阅读(37)  评论(0)    收藏  举报