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. 【刷题-LeeetCode】260. Single Number III

    Single Number III Given an array of numbers nums, in which exactly two elements appear only once and ...

随机推荐

  1. 在MessageBox的Show方法中如何无限使用参数值?

    今天发现在show方法中不能使用花括号的方式使用多个可变参数,经过查询得出结果.在show方法中是不存在花括号的方式使用参数的.在Console.WriteLine中是存在的,如下: 那么在show方 ...

  2. 根据文件夹的GUid找到该文件夹

    Guid guid = Guid.Parse(folderGuID); SPFolder folder = list.Folders[guid].Folder;

  3. Attribute 特性

    转载   不错   摘要:纠结地说,这应该算是一篇关于Attribute 的笔记,其中的一些思路和代码借鉴了他人的文笔(见本文底部链接).但是,由于此文对Attribute 的讲解实在是叫好(自夸一下 ...

  4. JS 頁面實時更新時間

    function startTime() { var today = new Date(); //定义日期对象 var yyyy = today.getFullYear(); //通过日期对象的get ...

  5. 通过C#去调用C++编写的DLL

    这个问题缠了我2个小时才弄出来,其实很简单.当对方提供一个dll给你使用时,你需要去了解这个dll 是由什么语言写的,怎么编译的,看它的编译类型.这样即使在没有头绪时,你可以先尝使用一些比较热门的编译 ...

  6. UIButton 使用imageEdgeInsets和titleEdgeInsets属性

    现在App的底部栏.侧边栏.顶部栏经常出现一些包含图像和文字的Item,以前用按钮上面添加label和imageView,  想想实在是对资源的浪费..                 图1 — 底部 ...

  7. WCF大文件传输服务

    由于项目需要,自己写一个基于WCF的大文件传输服务雏形.觉得有一定的参考价值,因此放在网上分享. 目前版本为v1.1特点如下: 1.文件传输端口为18650 2.上传和下载文件 3.支持获取文件传输状 ...

  8. WPF中TreeView数据结构解析

    XAML.CS代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...

  9. eclipse EE neon创建dynamic web project时,卡在installing dynamic web module facet,解决办法

    我们在用eclipse EE neon创建dynamic web project时,如果你发现底部状态栏一直卡在installing dynamic web module facet,永远到不了100 ...

  10. 批量缩放PNG图片.

    最近需要缩放N多图片, 找遍了互联网也没有找到方便使用的批量缩放工具.. 趁着周末写一个练手.. #include <iostream> #include <vector> # ...