Problem:

Given an array of numbers `nums`, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given `nums = [1, 2, 1, 3, 2, 5]`, return `[3, 5]`.

Note:

1. The order of the result is not important. So in the above example, `[5, 3]` is also correct.
2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.

Analysis:

```Sort a array is always a good beginning to find duplciates in a array.
But it would at least take O(nlogn) time in sorting the array.

Solution 1:
Basic idea:
step 1: sort the entire array.
step 2: in the sorted form, if a element does not have neighors share the same value wit it. It must be the single element we want to find.
Note: take care the first and last element, it may incure out of bound exception.

public int[] singleNumber(int[] nums) {
if (nums == null || nums.length <= 1)
return new int[0];
Arrays.sort(nums);
int[] ret = new int[2];
int count = 0;
for (int i = 0; i < nums.length; i++) {
boolean is_single = true;
if (i != 0)
is_single = is_single && (nums[i] != nums[i-1]);
if (i != nums.length - 1)
is_single = is_single && (nums[i] != nums[i+1]);
if (is_single)
ret[count++] = nums[i];
}
return ret;
}

Wrong logic:
If you use the default value of flag as "true", you must take care the logic you are going to implment. (|| or &&)
Initially, I have implemented following problemetic logic
-------------------------------------------------------------------
for (int i = 0; i < nums.length; i++) {
boolean is_single = true;
if (i != 0)
is_single = is_single || (nums[i] != nums[i-1]);
if (i != nums.length - 1)
is_single = is_single || (nums[i] != nums[i+1]);
if (is_single) {
ret[count] = nums[i];
count++;
}
}
-------------------------------------------------------------------

In the above code, the is_single would alway be true, since the intial default is true and I use "||" to pass around logic.
What I meant to do is "once it has a neighor, it should return false, and pass to the value".
The change is easy:
is_single = is_single && (nums[i] != nums[i-1]);

Even though the above solution is clear, there could a very elegant and genius solution for this problem.
But it requires strong understand of bit operation.
Key:
The magic rule of XOR.
a ^ a = 0;
a ^ b ^ a = 0;
a ^ b ^ c ^ a = b ^ c;
After the XOR operation, all numbers appear even times, would be removed from the final XOR value.
What's more, after "a ^ b ^ c ^ a = b ^ c", the set bits of "b ^ c" would only contain the digits that b are different from c.

Solving step:
step 1: XOR all elements in the array.

int xor = 0;
for (int i = 0; i < nums.length; i++) {
xor ^= nums[i];
}

step 2: get the rightmost bit of the set bit.
right_most_bit = xor & (~(xor-1));

step 3: divide the nums array into two set based on the set bit. (thus the single numbers: b, c would be placed into two different set). Then XOR at each set and get those two numbers.
for (int i = 0; i < nums.length; i++) {
if ((nums[i] & right_most_bit) == 0) {
ret[0] ^= nums[i];
} else{
ret[1] ^= nums[i];
}
}

Skills:
1. how to get the rightmost set bit?
right_most_bit = xor & (~(xor-1));
Reason:
The xor-1 would turn the rightmost set bit into 0, and bits after it becomes 1.
'1000001000' => '1000000111'
The not "~" operation would turn all bits into opposite bit (note the rightmost bitset has already been setted into 0)
'1000000111' => '0111111000'
The '&' operation would filter the setbit out.
'0111111000'
'1000001000'
'0000001000'

2. The set bit could be used a proper indicator to divide the original array into two sets.
if ((nums[i] & right_most_bit) == 0) {
ret[0] ^= nums[i];
} else{
ret[1] ^= nums[i];
}
Note the form of set bit: '0000001000', only the number share the same bit would not equal to "000000000...(integer: 0)"```

Solution:

```public class Solution {
public int[] singleNumber(int[] nums) {
if (nums == null || nums.length == 0)
return new int[0];
int[] ret = new int[2];
int xor = 0, right_most_bit = 0;
for (int i = 0; i < nums.length; i++) {
xor ^= nums[i];
}
right_most_bit = xor & (~(xor-1));
for (int i = 0; i < nums.length; i++) {
if ((nums[i] & right_most_bit) == 0) {
ret[0] ^= nums[i];
} else{
ret[1] ^= nums[i];
}
}
return ret;
}
}```

[LeetCode#260]Single Number III的更多相关文章

1. LeetCode 260. Single Number III(只出现一次的数字 III)

LeetCode 260. Single Number III(只出现一次的数字 III)

2. [LeetCode] 260. Single Number III 单独数 III

Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

3. Java [Leetcode 260]Single Number III

题目描述: Given an array of numbers nums, in which exactly two elements appear only once and all the oth ...

4. LeetCode 260 Single Number III 数组中除了两个数外，其他的数都出现了两次，找出这两个只出现一次的数

Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

5. Leetcode 260 Single Number III 亦或

在一个数组中找出两个不同的仅出现一次的数(其他数字出现两次) 同样用亦或来解决(参考编程之美的1.5) 先去取出总亦或值 然后分类,在最后一位出现1的数位上分类成 ans[0]和ans[1] a&am ...

6. [LeetCode] 260. Single Number III（位操作）

传送门 Description Given an array of numbers nums, in which exactly two elements appear only once and a ...

7. leetcode 136 Single Number, 260 Single Number III

leetcode 136. Single Number Given an array of integers, every element appears twice except for one. ...

8. leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)

136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...

9. 【一天一道LeetCode】#260. Single Number III

一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

随机推荐

1. CBOW Model Formula Deduction

Paper Reference: word2vec Parameter Learning Explained 1. One-word context Model In our setting, the ...

2. Rational Rose 2007 破解版安装过程

Rational Rose 2007 破解版安装过程 首先通过网站将软件下载,然后依照以下步骤进行: 选择第二项,下一步 一直点击next,出现如下,可以修改安装的目的文件夹 设置完路径之后出现如下, ...

3. BI系统与KPI指标的整合分析

今天我们要说的是信息化时代下关于企业运营的两个热词:BI系统和KPI指标.一直到现在,企业运营的方方面面都在被数据化,成为庞大信息流的一部分,这一庞大的信息流,正以我们自己都尚未完全意识到的速度和规模 ...

4. Java利用aspose-words将word文档转换成pdf（破解 无水印）

首先下载aspose-words-15.8.0-jdk16.jar包 http://pan.baidu.com/s/1nvbJwnv 引入jar包,编写Java代码 package doc; impo ...

5. 转：SELENIUM TIPS: CSS SELECTORS

6. C++ Primer ：第十章 ：泛型算法之再探迭代器以及其他算法

除了为每个容器定义的迭代器之外,标准库在头文件<iterator>还定义了额外集中迭代器, 包括: 插入迭代器,这些迭代器被绑定到一个容器上,可以向容器插入元素. 流迭代器,    这些迭 ...

7. leetcode第一刷_Validate Binary Search Tree

有了上面的教训,这道题就简单多了,什么时候该更新pre是明白的了,倒是有个细节,二叉搜索树中是不同意有相等节点的,所以题目的要求用黑体字标明了.写的时候注意就能够了. class Solution { ...

8. cassandra简单介绍与基本操作

项目中用到了cassandra,用来存储海量数据,且要有高效的查询:本博客就进行简单的介绍和进行一些基本的操作 一.使用场景: 是一款分布式的结构化数据存储方案(NoSql数据库),存储结构比Key- ...

9. Apex 中文件夹相关的单元测试

Salesforce 中的文件夹 在 Salesforce 中,我们可以建立各种文档.报表.仪表板.电子邮件模板等.它们都被保存在相应的文件夹中. Salesforce 的后端将这些文件夹保存为 Fo ...

10. linux-ubuntu 下R无法安装HH包的原因及解决方案

错误信息: configure: error: GNU MP not found, or not 4.1.4 or up, see http://gmplib.org ERROR: configura ...