leetcode
leetcode 101 ~ 150
只出现一次的数字

只出现一次的数字

难度:

标签:

题目描述

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

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

 

示例 1 :

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

示例 2 :

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

示例 3 :

输入:nums = [1]
输出:1

 

提示:

  • 1 <= nums.length <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。

代码结果

运行时间: 35 ms, 内存: 17.9 MB


// 思路:Java Stream 不太适合直接用于异或操作,但可以通过reduce方法来实现同样的功能。
 
import java.util.Arrays;
 
public class Solution {
    public int singleNumber(int[] nums) {
        return Arrays.stream(nums).reduce(0, (a, b) -> a ^ b);
    }
}

解释

方法:

这个题解使用了异或运算的性质来解决问题。异或运算有以下特点: 1. a ^ 0 = a 2. a ^ a = 0 3. a ^ b ^ a = b 利用这些特点,我们可以通过异或运算来找出只出现一次的数字。将数组中的所有数字进行异或运算,出现两次的数字会被异或为0,而只出现一次的数字和0做异或运算结果还是它本身。最终异或的结果就是只出现一次的数字。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么使用异或运算来解决这个问题?
异或运算有几个独特的性质,使得它非常适合解决这个问题。首先,任何数和0做异或运算,结果仍然是原数(a ^ 0 = a)。其次,任何数与其自身做异或运算,结果是0(a ^ a = 0)。最后,异或运算满足交换律和结合律,即a ^ b ^ a = b。这些性质使得我们可以通过一次遍历,使用异或运算处理所有数字,最终留下的就是唯一一个只出现一次的数字。出现两次的数字会在异或中彼此抵消变为0。
🦆
在异或操作中,为什么相同的数字异或的结果是0?
异或运算的定义是对二进制位进行运算,相同位得0,不同位得1。因此,当两个相同的数字进行异或运算时,它们的所有二进制位都相同,按位进行异或运算后结果都是0。例如,5的二进制表示是101,5 ^ 5的计算过程是101 ^ 101,每位都是相同的,结果就是000,即0。
🦆
异或运算的顺序是否会影响最终的结果?
不会。异或运算满足交换律和结合律。这意味着无论运算的顺序如何,其结果都是相同的。例如,a ^ b ^ c的结果与c ^ b ^ a或b ^ c ^ a相同。这使得在实际编程中我们无需担心元素的处理顺序,只需要确保每个元素都进行了一次异或运算。
🦆
如果在输入数组中有奇数个重复的数字,这个方法是否仍然有效?
这个方法只对每个数字出现偶数次,而有一个数字出现奇数次(特别是一次)的情况有效。如果有多个数字出现奇数次,或者一个数字出现的次数不是1而是其他奇数,这个方法无法正确找出所有这些只出现奇数次的数字。它只能找到一个数,这个数是数组中所有出现奇数次数字的异或结果。如果只有一个数字出现奇数次,它将正确返回那个数字。

相关问题

只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

 

示例 1:

输入:nums = [2,2,3,2]
输出:3

示例 2:

输入:nums = [0,1,0,1,0,1,99]
输出:99

 

提示:

  • 1 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

只出现一次的数字 III

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

 

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2:

输入:nums = [-1,0]
输出:[-1,0]

示例 3:

输入:nums = [0,1]
输出:[1,0]

 

提示:

  • 2 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • 除两个只出现一次的整数外,nums 中的其他数字都出现两次

丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

 

示例 1:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:

输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

示例 4:

输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

 

提示:

  • n == nums.length
  • 1 <= n <= 104
  • 0 <= nums[i] <= n
  • nums 中的所有数字都 独一无二

 

进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?

寻找重复数

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

 

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

示例 3 :

输入:nums = [3,3,3,3,3]
输出:3

 

 

提示:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

 

进阶:

  • 如何证明 nums 中至少存在一个重复的数字?
  • 你可以设计一个线性级时间复杂度 O(n) 的解决方案吗?

找不同

给定两个字符串 st ,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

请找出在 t 中被添加的字母。

 

示例 1:

输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。

示例 2:

输入:s = "", t = "y"
输出:"y"

 

提示:

  • 0 <= s.length <= 1000
  • t.length == s.length + 1
  • st 只包含小写字母