【LeetCode题解】136_只出现一次的数字

描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

方法一:列表操作

思路

新建一个变量(列表对象),遍历数组中的所有元素,如果元素在列表中存在,则删除该元素;如果元素在列表中不存在,则向列表中添加该元素。最后,列表中剩余的唯一元素就是我们找的唯一只出现一次的数字。

Java 实现

class Solution {
public int singleNumber(int[] nums) {
List<Integer> list = new LinkedList<>();
for (int num : nums) {
if (list.contains(num)) {
list.remove(new Integer(num));
} else {
list.add(num);
}
}
return list.get(0);
}
}

复杂度分析:

  • 时间复杂度:\(O(n^2)\)
  • 空间复杂度:\(O(n)\)

Python 实现

class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l = list()
for num in nums:
if num in l:
l.remove(num)
else:
l.append(num)
return l.pop()
# 超出时间限制

复杂度分析同上。

方法二:哈希表

思路

思路和方法一相同,只是存放数据的容器改用哈希表,由于哈希表查询操作的时间复杂度是 \(O(1)\) 的,因此,算法最终的时间复杂度降为 \(O(n)\)。

Java 实现

class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
if (map.containsKey(num)) {
map.remove(num);
} else {
map.put(num, 1);
}
}
return map.entrySet().iterator().next().getKey();
}
}

复杂度分析:

  • 时间复杂度:\(O(n)\)
  • 空间复杂度:\(O(n)\)

Python 实现

class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
d = dict()
for num in nums:
try:
d.pop(num)
except:
d[num] = 1
return d.popitem()[0]

复杂度分析同上。

方法三:数学运算

思路

由于数组中的数字除了唯一一个数字只出现一次外,其余都是出现两次的,因此,如果我们将所有的数字乘以 2 再减去数组中所有的元素,则可以得到只出现一次的数字,即

\[2 * (a_1 + a_2 + \ldots + a_n + a_x) - (a_1 + a_1 + \ldots + a_n + a_n + a_x) = a_x
\]

其中,\(a_1\) 到 \(a_n\) 是出现两次的数字,\(a_x\) 则是出现两次的数字。

Java 实现

class Solution {
public int singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
int arraySum = 0;
for (int num : nums) {
set.add(num);
arraySum += num;
} int doubleSum = 0;
for (int num : set) {
doubleSum += (2 * num);
} return doubleSum - arraySum;
}
}

复杂度分析:

  • 时间复杂度:\(O(n)\)
  • 空间复杂度:\(O(n)\)

Python 实现

class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
return 2 * sum(set(nums)) - sum(nums)

复杂度分析同上。

方法四:位运算

思路

先来回顾一下两个位运算:

  • 任何数与 0 异或都不改变它的值,即 \(a \oplus 0 = a\)
  • 任何数与其自身异或都为 0,即 \(a \oplus a = 0\)

假设题目中描述的数组为 \([a_1,\, a_1,\, a_2,\, a_2,\, \ldots,\, a_n,\, a_n,\, a_x]\) ,其中,\(a_x\) 只出现一次,其余的元素都出现两次。对该数组中的所有元素进行异或运算可得,

\[\begin{align*}
& \,\,a_1 \oplus a_1 \oplus \ldots \oplus a_n \oplus a_n \oplus a_x \\
= & \,\,(a_1 \oplus a_1) \oplus \ldots \oplus (a_n \oplus a_n) \oplus a_x \\
= &\,\, 0 \,\oplus \ldots \oplus 0 \,\oplus a_x \\
= &\,\, a_x
\end{align*}
\]

因此,只需要遍历数组中的所有元素,依次进行两两异或操作就可以找出只出现一次的元素。

Java 实现

class Solution {
public int singleNumber(int[] nums) {
int ret = nums[0];
for (int i = 1; i < nums.length; ++i) {
ret ^= nums[i];
}
return ret;
}
}

复杂度分析:

  • 时间复杂度:\(O(n)\)
  • 空间复杂度:\(O(1)\)

Python 实现

class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
ret = 0
for num in nums:
ret ^= num
return ret

复杂度分析同上。

【LeetCode题解】136_只出现一次的数字的更多相关文章

  1. LeetCode:137. 只出现一次的数字 II

    LeetCode:137. 只出现一次的数字 II 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. ...

  2. 【LeetCode】137. 只出现一次的数字 II(剑指offer 56-II)

    137. 只出现一次的数字 II(剑指offer 56-II) 知识点:哈希表:位运算 题目描述 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 .请你找出并返回 ...

  3. 力扣(LeetCode) 136. 只出现一次的数字

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...

  4. 《LeetBook》leetcode题解(9):Palindrome Number[E]——回文数字

    我现在在做一个叫<leetbook>的开源书项目,把解题思路都同步更新到github上了,需要的同学可以去看看 地址:https://github.com/hk029/leetcode 这 ...

  5. LeetCode 136:只出现一次的数字 Single Number

    题目: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. Given a non-empty array of integers, every e ...

  6. Leetcode题目136.只出现一次的数字(简单)

    ---恢复内容开始--- 题目描述: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外 ...

  7. Leetcode 137. 只出现一次的数字 II - 题解

    Leetcode 137. 只出现一次的数字 II - 题解 137. Single Number II 在线提交: https://leetcode.com/problems/single-numb ...

  8. 【LeetCode题解】二叉树的遍历

    我准备开始一个新系列[LeetCode题解],用来记录刷LeetCode题,顺便复习一下数据结构与算法. 1. 二叉树 二叉树(binary tree)是一种极为普遍的数据结构,树的每一个节点最多只有 ...

  9. 【LeetCode题解】225_用队列实现栈(Implement-Stack-using-Queues)

    目录 描述 解法一:双队列,入快出慢 思路 入栈(push) 出栈(pop) 查看栈顶元素(peek) 是否为空(empty) Java 实现 Python 实现 解法二:双队列,入慢出快 思路 入栈 ...

随机推荐

  1. MYC编译器源码之代码生成

    前面讲过语法的解析之后,代码生成方面就简单很多了.虽然myc是一个简单的示例编译器,但是它还是在解析的过程中生成了一个小的语法树,这个语法树将会用在生成exe可执行文件和il源码的过程中. 编译器在解 ...

  2. 初识powershell、nuget powershell 调试

    初识powershell.nuget powershell 调试 补充 此文仅当做powershell的初步认识体验,关于nuget包里此脚本的使用官方已在vs2017停止支持,请看此文文末 前言 老 ...

  3. C# npoi 从excel导入datagridviews 批量联网核查

    DataSet ds = new DataSet(); OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Fil ...

  4. item style edit in sharepoint 2013

    标题头添加属性:(如果需要使用ddwrt)xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime&quo ...

  5. MPLS 网络中的 MTU

    MPLS MTU的大小可以设置为64-65535之间,在MPLS网络中,标签的大小是计入到MTU中的,所以在MPLS网络MTU是一个常见的问题.     在Ethernet接口上,一般数据最长为150 ...

  6. 程序媛计划——python初级课时3~5

    产生1-10中的随机数: for 循环:所有可遍历对象都能用于for循环,如一个字符串. len(list),list中的元素类型可以各不相同:可以直接用下标对list元素赋值来更新列表 对字符串可以 ...

  7. Cordova - CordovaError: Promise rejected with non-error: 'ios-deploy was not found

    错误信息: CordovaError: Promise rejected with non-error: 'ios-deploy was not found. Please download, bui ...

  8. Debian&&ubuntu系安装MegaCli

    MegaCli这个命令可以用来监控raid状态.磁盘状况等,最近上了一批ubuntu系统跑openstack,问题是MegaCli在官网上只有rpm格式的包,没有deb的包,但是还是有办法解决的,rp ...

  9. js中call、apply、bind的使用

    写在前面的话 这三个方法都是来自Function.prototype上,所以所有的函数都可以使用. 他们有一个共同点,就是可以指定函数执行时的内部this指向. call和apply的区别在于参数的方 ...

  10. Vue-Router路由Vue-CLI脚手架和模块化开发 之 使用props替代路由对象的方式获取参数

    在上一章博文中使用路由对象$route获取参数时,组件和路由对象耦合,在这篇博文中就可以使用props来进行解耦: 1.在组件中使用props选项定义数据,接收参数: 2.在路由中,使用props选项 ...