Single Number题解整理
来源:互联网 发布:java开发的网游 编辑:程序博客网 时间:2024/06/05 20:54
Q: Given an array of integers, every element appears three times except for one. Find that single one.
如果是其余元素均出现两次,这个题目很容易解决,我们直接可以用xor,把所有的数异或之后的结果,便是出现一次的数字。但是这个题目其余元素出现的次数是三次,如果数组中的元素都是三个三个出现的,那么从二进制表示的角度,每个位上的1加起来,应该可以整除3。
基本方法:
如果有一个数x只出现一次,会是什么情况呢?
如果某个特定位上的1加起来,可以被3整除,说明对应x的那位是0,因为如果是1,不可能被3整除
如果某个特定位上的1加起来,不可以被3整除,说明对应x的那位是1
根据上面的描述,我们可以开辟一个大小为32的数组,第0个元素表示,A中所有元素的二进制表示的最低位的和,依次类推。
int get_high_bit_one(int num){for (int i = 31; i >=0; --i){if (!(num & (1<<i)))continue;return i;}}int find_once_number(int arr[], int len){int* bit_arr = new int[32];int num = 0;if (bit_arr != NULL){memset(bit_arr, 0, 32*sizeof(int));for (int index = 0; index < len; ++index){int bit_nums = get_high_bit_one(arr[index]);for (int bit_idx = 0; bit_idx <= bit_nums; ++bit_idx){bit_arr[bit_idx] += (arr[index] & (1<<bit_idx))>>bit_idx;}}for (int i = 0; i < 32; ++i){if (bit_arr[i]%3)bit_arr[i] = 1;elsebit_arr[i] = 0;}for (int i = 0; i < 32; ++i){num += bit_arr[i]*(1<<i);}delete[] bit_arr;}return num;}
位操作is coming…
有没有更加简洁的方法呢?我们可以从位操作上入手这个问题。用二进制模拟三级制的运算。
B1
B0
Input
B1`
B0`
0
0
1
0
1
0
1
1
1
0
1
0
1
0
0
0
0
0
0
0
0
1
0
0
1
1
0
0
1
0
通过位之间的转换,我们可以得到如下代码.
int singleNumber(int A[], int n) { int one = 0, two = 0; for (int i = 0; i < n; i++) { int one_ = (one ^ A[i]) & ~two; int two_ = A[i] & one | ~A[i] & two; one = one_; two = two_; } return one; }
用ones记录到当前计算的变量为止,二进制1出现“1次”(mod 3 之后的 1)的数位。用twos记录到当前计算的变量为止,二进制1出现“2次”(mod 3 之后的 2)的数位。当ones和twos中的某一位同时为1时表示二进制1出现3次,此时需要清零。即用二进制模拟三进制计算。最终ones记录的是最终结果。
int singleNumber(int A[], int n) { int ones = 0, twos = 0, xthrees = 0; for(int i = 0; i < n; ++i) { twos |= (ones & A[i]); ones ^= A[i]; xthrees = ~(ones & twos); ones &= xthrees; twos &= xthrees; } return ones;}
更好的方法,而且可以扩展到多位计算的方法。
int getSingleNumber_v2(int a[], int len){if (a == NULL)return 0;int x0 = ~0, x1 = 0, x2 = 0, tmp;for (int i = 0; i < len; ++i){tmp = x2;x2 = (x1 & a[i]) | (x2 & ~a[i]); x1 = (x0 & a[i]) | (x1 & ~a[i]); x0 = (tmp & a[i]) | (x0 & ~a[i]);}return x1;}
利用上述方法可以解决这个扩展问题:
Q:Given an array ofintegers, every element appears k times except for one. Find that single one who appears l times.
int getSingleNumber_v3(int A[], int len, int k, int l){ if (A == NULL) return 0; int t; int* x = new int[k]; memset(x, 0, k*sizeof(int)); x[0] = ~0; for (int i = 0; i < len; i++) { t = x[k-1]; for (int j = k-1; j > 0; j--) { x[j] = (x[j-1] & A[i]) | (x[j] & ~A[i]); } x[0] = (t & A[i]) | (x[0] & ~A[i]); } return x[l];}
- Single Number题解整理
- 【LeetCode题解】Single Number
- LeetCode题解:Single Number
- LeetCode题解:Single Number
- LeetCode题解:Single Number
- Single Number III 题解
- 【LeetCode题解】Single Number II
- [题解][LeetCode][Single Number II]
- LeetCode题解:Single Number II
- LeetCode题解:Single Number II
- LeetCode题解:Single Number III
- leetcode 136. Single Number 题解
- 【牛客网】single-number系列题解
- Leetcode题解 136. Single Number
- LeetCode Single Number系列题解
- LeetCode 136 Single Number题解
- 【Leetcode题解】136.Single Number
- Lintcode82 Single Number solution题解
- GIT和SVN之间的五个基本区别
- C++ Primer 3rd 读书笔记1/2
- html 锚点用法
- 06.黑马程序员-基本运算、类型转换
- 编码器精度软件提高方式
- Single Number题解整理
- android 动画结束后控件不能点击问题和View闪的问题
- 编译系统和解释系统的区别
- 士兵杀敌(五)
- Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
- JSP连接access数据库
- 实现图像pyramids
- ubuntu wine使用代理安装
- Internal Error (classFileParser.cpp:3075), pid=520, tid=3636 Error: ShouldNotReachHere()