『面试题』寻找最少的数字

『题目』:

  Assume we have a sequence that contains N N N numbers of type long. And we know for sure that among this sequence each number does occur exactly n times except for the one number that occurs exactly m times ( 0 < m < n ) (0 < m < n) (0<m<n). How do we find that number with O ( N ) O(N) O(N) operations and O ( 1 ) O(1) O(1) additional memory?
Example. We know that n=3 \textbf{n=3} n=3 and m=2 \textbf{m=2} m=2
 The sequence ( N=8 ) (\textbf{N=8}) (N=8) is : 5   11   5   2   11   5   2   11 5\ 11\ 5\ 2\ 11\ 5\ 2\ 11 5 11 5 2 11 5 2 11
 And the right answer is 2 2 2 in this partcular case because it occurs only twice.

『题意』:

 题目的意思是给定一堆数字(Long型),这堆数字是乱序的,其中有些数字会出现 n n n次,而只有1个数字会出现 m m m次,如果通过 O ( N ) O(N) O(N)的时间复杂度和 O ( 1 ) O(1) O(1)复杂度找到这个数字呢?

『题解』:

 这道题有个技巧,这要将数字拆成 b i t bit bit,这里有个关键条件是 ( 0 < m < n ) (0 < m < n) (0<m<n),那么如果我将每一个数字的当前bit求和,然后对 n n n取余,那么如果不为 0 0 0,说明当前 b i t bit bit 有值,将所有 b i t bit bit 拆一次,那么余数位置就对应的是要求的值。
举例:

		5		5		5		2		2
bit0=	1	+	1	+	1	+	0	+	0	=	3	%	3	=	0
bit1=	0	+	0	+	0	+	1	+	1	=	2	%	3	=	2
bit2=	1	+	1	+	1	+	0	+	0	=	3	%	3	=	0
bit3=	0	+	0	+	0	+	0	+	0	=	0	%	3	=	0
所以最后答案是【0010】=2

『实现』:

import java.util.Scanner;

/**
 * Author:
 *      Gavinjou大笨象
 * Date:
 *      2019-05-01
 * Description:
 *      题解
 */
public class job1 {
    //长度为64bit
    private static int[] ansnum;
    //读入的数字长度
    private static long[] num;
    private static int n,m,N;
    private static long ans;

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        N=in.nextInt();
        n=in.nextInt();
        m=in.nextInt();

        num = new long[N];
        ansnum = new int[64];
        //读入数字
        for(int i = 0; i < N; i++)
        {
            num[i] = in.nextInt();
        }

        for(int i = 0; i < 64; i++)
        {
            for(int j = 0; j < N; j++)
            {
                //拆出每一个数字的字节
                ansnum[i] += (num[j] >> i) & 1;
            }
            //对和求余
            ansnum[i] %= n;
            ansnum[i] = ansnum[i] > 0 ? 1 : 0;
        }

        //计算最后答案
        for(int i = 0; i < 64 ; i++)
        {
            ans += (ansnum[i] << i);
        }

        System.out.println(ans);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值