题解 | #数组中只出现一次的数(其它数出现k次)#

数组中只出现一次的数(其它数出现k次)

http://www.nowcoder.com/practice/5d3d74c3bf7f4e368e03096bb8857871

数组中只出现一次的数(其它数出现$k$次)

问题描述:给定一个整型数组 $arr $和一个整数 $k(k>1)$k。已知 $arr$ 中只有 1 个数出现一次,其他的数都出现 $k$ 次。请返回只出现了 1 次的数。
示例
输入:[5,4,1,1,5,1,5],3 
返回值:4

方法一

思路分析

     本题我们很容易就能想到,先将整个数组进行排序,那么数组中存在的$k$个数就会连续放在一起,此时从数组开始元素处向后遍历,当相邻的两个元素相等时,那么这一子序列必然是$k$个相等的数,那么直接跳过这个$k$个数,继续下一次的比较,因为比较的位置只会在资格连续子序列的开始位置,如果相邻的元素不相等那么直接就可以找到只出现一次的数。

图解

输入:[5,4,1,1,5,1,5],3 
首先对数组进行排序,得到[1,1,1,4,5,5,5]
相当于对数组进行了一次如下的划分

图解过程如下:


C++核心代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param arr intvector 
     * @param k int 
     * @return int
     */
    int foundOnceNumber(vector<int>& arr, int k) {
        // write code here
        int n=arr.size();
        sort(arr.begin(), arr.end());//对数组元素排序
        int ans=1;
        for(int i=0;i<n-1;i++)
        {
            if(arr[i]==arr[i+1])//如果存在两个元素相同,那么直接跳过这k-1个数进入下一次比较
                i+=k-1;//直接跳过这k-1个相等的数
            else
            {
                return arr[i];//一个数不属于一组k个数中,那么就找到了出现一次的数
            }
                
        }
        return arr[n-1];//单独的数在数组最后的位置
        
    }
};

复杂度分析

  • 时间复杂度:首先需要对数组进行排序,时间复杂度为,一层循环遍历,里面有一次比较操作,因此时间复杂度为$O(n)$,因此总的时间复杂度为
  • 空间复杂度:  空间复杂度为$O(1)$

方法二

思路分析

     根据异或的思想:如果两个相同的数异或则结果为0 ,任何数与0 的异或是其本身,如果将整个数组所有元素相互异或,输出只有奇数个的元素,然后这种方法只适用于$k$为偶数的情况。因此使用位运算的办法,由于只有一个数出现一次,其余数出现$k$次,定义一个32维的数组,将数组中的所有元素按二进制数按位相加后存放在数组中,之后遍历32维的数组,对数组中每一位模$k$,模$k$如果有余数那么即为只出现一次的那个数的位,之后将取模后的数转换为二进制即可。

实例分析

  • 首先将数组中的数转换为二进制后按位相加并存储在32维的数组中
  • 之后对32维数组中的每一位模$k$,并将结果保存在该位中
  • 对剩余的结果转换为十进制
输入:[5,4,1,1,5,1,5],3 
转换为二进制:1的二进制为0001,4的二进制为0100,5的二进制为0101   
之后按位相加存储在32维的数组中$bits[]=\{0,4,0,6\}$,之后对数组中的每一位模3,得到$bits[]=\{0,1,0,0\}$,将其转换为十进制即为4

JAVA核心代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param arr int一维数组 
     * @param k int 
     * @return int
     */
    public int foundOnceNumber (int[] arr, int k) {
        // write code here
        int[] bits = new int[32];
        for (int i = 0; i < 32; i++)
        {
            for (int num : arr)
            {
                 bits[i] += (num >> i) & 1;//对数组元素中所有的数转换为二进制后按位相加
            }
            
           
        }
        int res = 0;
        for (int i = 0; i < 32; i++)
        {
            int num = bits[i];
            num %= k;//对32维的数组每一位模k,剩余的即为只出现一次的数的位
            res += num << i;//二进制数转换为十进制
        }
        return res;
    }
}

复杂度分析

  • 时间复杂度:存在两层循环遍历,每次循环次数为32,因此时间复杂度为$O(64)$
  • 空间复杂度:   借助于一个32维的数组,因此空间复杂度为$O(32)$
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
4018次浏览 46人参与
# 离家近房租贵VS离家远但房租低,怎么选 #
16907次浏览 137人参与
# 米连集团26产品管培生项目 #
7311次浏览 226人参与
# 春招至今,你的战绩如何? #
15816次浏览 145人参与
# 你的实习产出是真实的还是包装的? #
3098次浏览 53人参与
# 沪漂/北漂你觉得哪个更苦? #
1553次浏览 41人参与
# 巨人网络春招 #
11527次浏览 224人参与
# HR最不可信的一句话是__ #
1091次浏览 32人参与
# AI面会问哪些问题? #
946次浏览 23人参与
# 你做过最难的笔试是哪家公司 #
1247次浏览 22人参与
# AI时代,哪个岗位还有“活路” #
2853次浏览 51人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152905次浏览 889人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
8021次浏览 43人参与
# XX请雇我工作 #
51155次浏览 171人参与
# 简历第一个项目做什么 #
32148次浏览 361人参与
# 简历中的项目经历要怎么写? #
311051次浏览 4265人参与
# 投格力的你,拿到offer了吗? #
178339次浏览 891人参与
# 你最满意的offer薪资是哪家公司? #
76981次浏览 375人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187605次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64760次浏览 890人参与
# 如果重来一次你还会读研吗 #
230018次浏览 2011人参与
# 正在春招的你,也参与了去年秋招吗? #
364353次浏览 2642人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务