『题目』:
Assume we have a sequence that contains NNN 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 115\ 11\ 5\ 2\ 11\ 5\ 2\ 115 11 5 2 11 5 2 11
And the right answer is 222 in this partcular case because it occurs only twice.
『题意』:
题目的意思是给定一堆数字(Long型),这堆数字是乱序的,其中有些数字会出现nnn次,而只有1个数字会出现mmm次,如果通过O(N)O(N)O(N)的时间复杂度和O(1)O(1)O(1)复杂度找到这个数字呢?
『题解』:
这道题有个技巧,这要将数字拆成 bitbitbit,这里有个关键条件是(0<m<n)(0 < m < n)(0<m<n),那么如果我将每一个数字的当前bit求和,然后对nnn取余,那么如果不为000,说明当前 bitbitbit 有值,将所有 bitbitbit 拆一次,那么余数位置就对应的是要求的值。
举例:
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);
}
}
博客围绕一道算法题展开,题目是给定一堆乱序的Long型数字,部分数字出现n次,仅1个数字出现m次(0<m<n),需用O(N)时间复杂度和O(1)复杂度找出该数字。题解是将数字拆成bit,对每个数字的当前bit求和后对n取余,余数位置对应所求值。
467

被折叠的 条评论
为什么被折叠?



