您的位置:首页 > 编程语言 > Java开发

leetcode oj java 260. Single Number III

2017-01-04 11:34 295 查看
一、问题描述:

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:

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

二、解决思路:

我们知道如果数组中是只有一个出现一次,其余都出现两次的话,可以直接用异或的方式得到这个数字(一个数字异或自己得到0,那么出现次数为2的数字异或完之后就是0,单独出现一次

的数字异或0变成它自己)。

现在数组中有两个数字只出现一次。如果我们把这个数组分成两个数组,每个数组中包含一个只出现一次的数字以及其余数字都出现两次,分别对每个数组进行上述的操作就可以得到只出现

一次的数字。

那么如果划分数组才可以保证每个数组中包含一个只出现一次的数字以及其余数字都出现两次?

遍历整个数组,求得异或的值。 这个值相当于两个只出现一次的数字的异或,必然不为0. 我们找到第一个为1的位置n。遍历整个数组。如果元素的第n位是1,那就放到数组l1中,否则放到数

组l2中。 此时l1中是两个只出现一次的数字中第n位是1的数字以及剩下的出现两次的数值中第n位为1的数字。l2中是剩下的数字。即根据第n位是否为1把那些出现两次的数字分为2组。(相同的数字

不可能分别出现在两个数组中了)

三、代码:

public class Solution {
public int[] singleNumber(int[] nums) {
int[] re = new int[2];
int tmp = nums[0];
for (int i = 1; i < nums.length; i++) {
tmp = tmp ^ nums[i];
}
// find first one
int n = 0;
while ((tmp & 1) == 0) {
tmp = tmp >> 1;
n++;
}
// split
List<Integer> l1 = new ArrayList<Integer>();
List<Integer> l2 = new ArrayList<Integer>();
for (int i = 0; i < nums.length; i++) {

int t = nums[i];
int bit = n;
while (bit > 0) {
t = t >> 1;
bit--;
}
if ((t & 1) == 0) {
l1.add(nums[i]);
} else {
l2.add(nums[i]);
}

}
re[0] = l1.get(0);
for (int i = 1; i < l1.size(); i++) {
re[0] = re[0] ^ l1.get(i);
}
re[1] = l2.get(0);
for (int i = 1; i < l2.size(); i++) {
re[1] = re[1] ^ l2.get(i);
}
return re;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: