『题目』:
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);
}
}