Single Number II
Posted codingEskimo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Single Number II相关的知识,希望对你有一定的参考价值。
The problem is similar to Single Number, two ways can solve it:
1. Traditional way: HashMap 参考之前的note
2. Bit Operation:
http://www.wengweitao.com/lintcode-single-number-i-ii-iii-luo-dan-de-shu.html
class Solution { public: /** * @param A : An integer array * @return : An integer */ bool isBit1(int num, int index){ int mask = 1 << index; // left shift 1 to the bit we want to calculate eg. 0100 return (num & mask); // & 0100 will set all other bit to be 0 except 1. // 1 will be same as original, so it either to be a number or 0000 } int singleNumberII(vector<int> &A) { // write your code here int n = A.size(); int res = 0; for(int i = 0; i < 32; ++i){ int count = 0; for ( int j = 0; j < n; ++j){ if(isBit1(A[j], i)){ count++; } } res |= (count % 3) << i; } return res; } };
思路1:
对int的32bit的各个位中1出现的次数,对数组中所有元素的逐个进行统计,然后对每个bit对3取余,最终的结果就是只出现一次的数字。
public class Solution { /** * @param A : An integer array * @return : An integer */ public int singleNumberII(int[] A) { // write your code here int n = A.length; int once = 0; int twice = 0; int third = 0; for (int i = 0; i < n; ++i){ twice |= once & A[i]; // if it shows once, and A[i] has it again, it should set to twice; once ^= A[i]; //if it shows once, and A[i] has it again, it has been send to twice, once has to be set back to zero; third = once & twice; // if it shows once, and it shows twice, it shows three times; once &= ~third; //once it set to three times, set back once/twice to be zero; twice &= ~third; } return once; } }
思路2: 利用掩码的思想。
- 变量once作为一个掩码,若once的二进制表示中的一个位置为1,表示目前使该位为1的数只出现一次
- 变量twice作为一个掩码,若twice的二进制表示中的一个位置为1,表示目前使该位置为1的数出现了2次
- 变量third作为一个掩码,若third的二进制表示中的一个位置为1,表示目前使该位置为1的数出现了3次
- 若之前出现一次(表示为once中对应的位为1),A[i]中又出现(表示为A[i]中对应的位置为1),那么twice中对应的位就为1;
- 若之前的once中出现,而A[i]中又出现,那么就不是出现一次,将对应的位取0
- once中出现一次,twice出现两次,也就是出现了3次
- 需要将once和twice中出现3次的位都置为0
以上的代码涉及到比较多的位运算,可能不大好理解。举个具体的例子:
once: 100101 使第1、3、6个bit为1的数出现3次
twice: 010101 使第1、3、5个bit为1的数出现了2次
third: 000101 根据once和twice可以得到third,第1和3个bit为1的数出现了3次。
以上算法的时间复杂度为O(n),空间复杂度为O(1)。
扩展一:
给定一个包含n个整数的数组,除了一个数出现二次外所有的整数均出现三次,找出这个只出现二次的整数。ones记录1出现一次的数,twos记录1出现2次的数,容易知道twos记录的即是最终结果。
扩展二:
给定一个包含n个整数的数组,有一个整数x出现b次,一个整数y出现c次,其他所有的数均出现a次,其中b和c均不是a的倍数,找出x和y。使用二进制模拟a进制,累计二进制位1出现的次数,当次数达到a时,对其清零,这样可以得到b mod a次x,c mod a次y的累加。遍历剩余结果(用ones、twos、fours...变量表示)中每一位二进制位1出现的次数,如果次数为b mod a 或者 c mod a,可以说明x和y的当前二进制位不同(一个为0,另一个为1),据此二进制位将原数组分成两组,一组该二进制位为1,另一组该二进制位为0。这样问题变成“除了一个整数出现a1次(a1 = b 或 a1 = c)外所有的整数均出现a次”,使用和上面相同的方式计算就可以得到最终结果,假设模拟a进制计算过程中使用的变量为ones、twos、fours...那么最终结果可以用ones | twos | fours ...表示。
以上是关于Single Number II的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III