作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/single-number-iii/description/

题目描述

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?

题目大意

一个数组中,有些元素出现了两次,有两个元素各自只出现1次,找出这两个元素。

解题方法

异或

想到这个系列的第一个题,就是找出单个的只出现一次的字符。做法是异或操作。这个题也是用异或。

把所有的数字进行一次异或,得到的是只出现了一次的两个数字的异或。

这两个数字不等,因此他们的二进制必定至少1位不同,即异或结果中为1的那位(一个数字的该位为1,另个数字的该位为0)。找出从右向左的第一个不同的位置(异或值为1的位置),给mask在该位置设置成1,mask的其余位置是0. mask存在的意义在于我们能通过该位置来分辨出两个只出现了一次的数字。

然后技巧性的来了:再进行一次异或操作。

每个数字都跟mask相与。通过与的结果为0和为1,即可区分出两个数字。

我刚开始有点不明白的是,为什么把所有的元素都重新异或了?其实,因为除了这两个元素以外,其他的元素都出现了两次,这两次相同的数字的和mask的与操作的结果是相同的,所以会被异或两次抵消掉。

一言以蔽之,先通过异或找出两个元素的异或结果。再根据异或结果的出现为1的位置作为mask,mask的二进制只有1位是1,也就是只看两个元素的该位置。最后,通过与操作判断该位置是0还是1区分两个元素。

参考:https://segmentfault.com/a/1190000004886431

代码:

class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
xor = 0
num1, num2 = 0, 0
for num in nums:
xor ^= num
mask = 1
while xor & mask == 0:
mask = mask << 1
for num in nums:
if num & mask == 0:
num1 ^= num
else:
num2 ^= num
return [num1, num2]

C++代码如下:

class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int res = 0;
for (int n : nums) res ^= n;
int a = 0, b = 0;
int mask = 1;
while ((mask & res) == 0) mask <<= 1;
for (int n : nums) {
if (n & mask)
a ^= n;
else
b ^= n;
}
return {a, b};
}
};

字典

使用字典直接求只出现一次的数字即可。

class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
count = collections.Counter(nums)
res = []
for num, c in count.items():
if c == 1:
res.append(num)
return res

C++代码如下:

class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
map<int, int> count;
for (int n : nums) count[n] ++;
vector<int> res;
for (auto p : count)
if (p.second == 1)
res.push_back(p.first);
return res;
}
};

日期

2018 年 3 月 3 日
2018 年 11 月 24 日 —— 周六快乐
2018 年 12 月 10 日 —— 又是周一!

【LeetCode】260. Single Number III 解题报告(Python & C++)的更多相关文章

  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. [LeetCode#260]Single Number III

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

  4. LeetCode - 136. Single Number - ( C++ ) - 解题报告 - 位运算思路 xor

    1.题目大意 Given an array of integers, every element appears twice except for one. Find that single one. ...

  5. Java [Leetcode 260]Single Number III

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

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

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

  7. Leetcode 260 Single Number III 亦或

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

  8. [LeetCode] 260. Single Number III(位操作)

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

  9. leetcode 136 Single Number, 260 Single Number III

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

随机推荐

  1. window修改dns本地文件

    文件地址: C:\Windows\System32\drivers\etc 先修改权限: 最后用记事本打开编辑保存即可

  2. perl 转置矩阵

    这里提供一个转置矩阵的perl脚本,R语言中的t()函数同样也能实现转置 1 use strict; 2 3 open A,"$ARGV[0]"; 4 5 my %ha; 6 my ...

  3. Excel-电话号码隐藏某几个数为*,起到保护信息作用;

    9.电话号码隐藏某几个数为*,起到保护信息作用: 方法一: =SUBSTITUTE(AG2,MID(AG2,4,5),"*****") 解释函数: MID(目标字符串,裁剪起始位置 ...

  4. 基本绘图函数:plot的使用

    注意:"##"后面是程序输出结果 例如: par("bg") # 命令 ## [1] "white" # 结果 基本绘图函数: plot:散 ...

  5. 16. Linux find查找文件及文件夹命令

    find的主要用来查找文件,查找文件的用法我们比较熟悉,也可用它来查找文件夹,用法跟查找文件类似,只要在最后面指明查找的文件类型 -type d,如果不指定type类型,会将包含查找内容的文件和文件夹 ...

  6. Java事务与JTA

    一.什么是JAVA事务 通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令.更简答的说就是:要么 ...

  7. go channel 概述 - 管道

    概述 unix/linux OS 的一个进程的输出可以是另一个进程的输入,这些进程使用stdin与stdout设备作为通道,在进程之间传递数据. 同样的,GO中有io.Reader与io.Writer ...

  8. linux系统的一些常用命令

    cd 进入某个目录 ifconfig 查看本机的ip cp (要复制的文件的位置) (要把文件复制的位置) ll 查看文件下,文件的操作权限 ls查看该文件夹下的有那些文件和文件夹 vi filena ...

  9. String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?

    原理知识: 如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的.如果在函数中改变了副本的 值不会改变原始的值. 如果参数类型是引用类型,那 ...

  10. 7、Redis五大数据类型---集合(Set)

    一.集合(Set)简介 Set是string类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据. Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1). ...