【剑指offer之数组中只出现一次的数字】
2017-04-25 23:24
351 查看
【链接】:http://ac.jobdu.com/problem.php?pid=1351
【题目】:
题目1351:数组中只出现一次的数字
时间限制:1 秒内存限制:32 兆特殊判题:否提交:3381解决:979
题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组大小。2<=n <= 10^6。
第二行包含n个整数,表示数组元素,元素均为int。
输出:
对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
样例输入:
8
2 4 3 6 3 2 5 5
样例输出:
4 6
【思路】:
分析:这是一道很新颖的关于位运算的面试题。
首先我们考虑这个问题的一个简单版本:一个数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。
这个题目的突破口在哪里?题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现依次的数字,因为那些出现两次的数字全部在异或中抵消掉了。
有了上面简单问题的解决方案之后,我们回到原始的问题。如果能够把原数组分为两个子数组。在每个子数组中,包含一个只出现一次的数字,而其他数字都出现两次。如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。
我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1的位的位置,记为第N位。现在我们以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0。
现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。因此到此为止,所有的问题我们都已经解决。
基于上述思路,我们不难写出如下代码:
【代码】:
is_bit1:作用是判断在num二进制表示中从右数起的indexbit为是否为1。
Find_first_bit1:在整数num的二进制表示中找到最右边是1的位。
Find_nums_appear_once:RT。
参考:【博客】:http://zhedahht.blog.163.com/
【题目】:
题目1351:数组中只出现一次的数字
时间限制:1 秒内存限制:32 兆特殊判题:否提交:3381解决:979
题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组大小。2<=n <= 10^6。
第二行包含n个整数,表示数组元素,元素均为int。
输出:
对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
样例输入:
8
2 4 3 6 3 2 5 5
样例输出:
4 6
【思路】:
分析:这是一道很新颖的关于位运算的面试题。
首先我们考虑这个问题的一个简单版本:一个数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。
这个题目的突破口在哪里?题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现依次的数字,因为那些出现两次的数字全部在异或中抵消掉了。
有了上面简单问题的解决方案之后,我们回到原始的问题。如果能够把原数组分为两个子数组。在每个子数组中,包含一个只出现一次的数字,而其他数字都出现两次。如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。
我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1的位的位置,记为第N位。现在我们以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0。
现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。因此到此为止,所有的问题我们都已经解决。
基于上述思路,我们不难写出如下代码:
【代码】:
#pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <set> #include <stack> #include <math.h> #include <map> #include <queue> #include <deque> #include <vector> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 1e6+10; const LL MOD = 999999997; int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}}; int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}}; /*Super waigua */ #define INLINE __attribute__((optimize("O3"))) inline INLINE char NC(void) { static char buf[100000], *p1 = buf, *p2 = buf; if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, 100000, stdin); if (p1 == p2) return EOF; } return *p1++; } INLINE void read(int &x) { static char c; c = NC(); int b = 1; for (x = 0; !(c >= '0' && c <= '9'); c = NC()) if(c == '-') b = -b; for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = NC()); x *= b; } int a[maxn]; unsigned int Find_first_bit1(int num) { int indexbit=0; while( ((num&1)==0) && (indexbit< 8*sizeof(int)) ) { num>>=1; ++indexbit; } return indexbit; } bool is_bit1(int num,unsigned int indexbit) { num = num >>indexbit; return (num & 1 ); } void Find_nums_appear_once(int a[],int n) { if(a== NULL || n< 2) return; int ret=0; for(int i=0; i<n; ++i) ret^=a[i]; unsigned int indexof1 = Find_first_bit1(ret); int num1 =0,num2 =0; for(int j=0; j<n; ++j) { if(is_bit1(a[j],indexof1)) num1^=a[j]; else num2^=a[j]; } printf("%d %d\n",num1<num2?num1:num2,num1>num2?num1:num2); } int main() { // freopen("in.txt","r",stdin); ios::sync_with_stdio(false); int n; while(cin>>n) { for(int i=0; i<n; ++i) cin>>a[i]; Find_nums_appear_once(a,n); } return 0; } /************************************************************** Problem: 1351 User: herongwei Language: C++ Result: Accepted Time:710 ms Memory:5420 kb ****************************************************************/
is_bit1:作用是判断在num二进制表示中从右数起的indexbit为是否为1。
Find_first_bit1:在整数num的二进制表示中找到最右边是1的位。
Find_nums_appear_once:RT。
参考:【博客】:http://zhedahht.blog.163.com/
相关文章推荐
- 剑指Offer:面试题40 数组中只出现一次的数字
- [剑指offer][面试题40]数组中只出现一次的数字
- 剑指offer 6.3 知识迁移能力4- 数组中只出现一次的数字
- 剑指offer解题报告(Java版)——数组中只出现一次的数字 40
- 剑指offer第40题 数组中只出现一次的数字
- 剑指offer面试题40:数组中只出现一次的数字
- 【剑指offer】Q40:数组中出现一次的数字
- 剑指offer面试题40-数组中只出现一次的数字
- 剑指offer 数组中只出现一次的数字
- 剑指offer-40 数组中只出现一次的数字
- 剑指 offer set 18 数组中只出现一次的数字
- 剑指Offer之 - 数组中只出现一次的数字
- 剑指offer——面试题40:数组中只出现一次的数字
- 剑指offer——数组中只出现一次的数字
- 整形数组中只出现一次的数字(剑指Offer,九度OJ)
- 剑指offer--数组中只出现一次的数字
- 剑指offer 面试题40—数组中两个只出现一次的数字
- [剑指offer]面试题40:数组中只出现一次的数字
- 【剑指offer】数字数组中只出现一次(2)
- 【剑指Offer学习】【面试题40:数组中只出现一次的数字】