给定一个数组,除了一个元素只出现1次,其它元素都出现3次。设计一个算法找出只出现一次的元素。要求时间复杂度为O(n),额外空间O(1)。
输入: arr[] = {12, 1, 12, 3, 12, 1, 1, 2, 3,3}
输出: 2
除了2其它都出现3次。
输入: arr[] = {10, 20, 10, 30, 10, 30, 30}
输出: 20
除了20其它都出现3次。
class GFG {
static int getSingle(int arr[], int n)
{
int ones = 0, twos = 0;
int common_bit_mask;
for (int i = 0; i < n; i++) {
twos = twos | (ones & arr[i]);
ones = ones ^ arr[i];
common_bit_mask = ~(ones & twos);
ones &= common_bit_mask;
twos &= common_bit_mask;
}
return ones;
}
public static void main(String args[])
{
int arr[] = { 3, 3, 2, 3 };
int n = arr.length;
System.out.println("只出现一次的元素是 " + getSingle(arr, n));
}
}
输出:
只出现一次的元素是 2
记录每个bit为1的次数。出现1次存在ones上。出现2次存在twos上。出现3次清除掉。
几个疑惑?
答:以 { 3, 3, 2, 3 }为例。第一次遍历,ones = 3。*第二次遍历,arr[1] =3。 ones需要变成0。需要抵消掉arr[1]。有点类似消消乐的意思。所以用异或操作。
答:ones & twos。
以{ 3, 3, 2, 3 }为例
twos = tows|(ones&arr[0])
twos = 00000000|(00000000&00000011) =00000000
ones = ones^arr[0]
ones = 00000000^00000011 = 00000011
common_bit_mask = ~(ones & twos)
common_bit_mask = ~(00000011 & 00000000) =11111111
ones & = common_bit_mask
ones = 00000011
twos & = common_bit_mask
twos = 00000000
ones = 3,twos = 0
twos = tows|(ones&arr[1])
twos = 00000000|(00000011&00000011) =00000011
ones = ones^arr[1]
ones = 00000011^00000011 = 00000000
common_bit_mask = ~(ones & twos)
common_bit_mask = ~(00000000 & 00000011) =11111111
ones & = common_bit_mask
ones = 00000000
twos & = common_bit_mask
twos = 00000011
ones = 0,twos = 3
twos = tows|(ones&arr[2])
twos = 00000011|(00000000&00000010) =00000011
ones = ones^arr[2]
ones = 00000000^00000010 = 00000010
common_bit_mask = ~(ones & twos)
common_bit_mask = ~(00000010 & 00000011) =11111101
ones & = common_bit_mask
ones = 00000010 & 11111101 = 00000000
twos & = common_bit_mask
twos = 00000011 & 11111101 = 00000001
ones = 0,twos = 1
twos = tows|(ones&arr[3])
twos = 00000001|(00000000&00000011) =00000001
ones = ones^arr[3]
ones = 00000000^00000011 = 00000011
common_bit_mask = ~(ones & twos)
common_bit_mask = ~(00000011 & 00000001) =11111110
ones & = common_bit_mask
ones = 00000011 & 11111110 = 00000010
twos & = common_bit_mask
twos = 00000001 & 11111110 = 00000000
ones = 2,twos = 0