这一系列时间复杂度均要求
,空间复杂度均要求
,所以不适用哈希表的方式
问题一
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例:
输入: [4,1,2,1,2]
输出: 4
思路: (异或)运算(相同为0,不同为1)可以用来找到两个数字二进制之间的差异,如果两个数字相同进行异或结果为0,否则不为零,
。异或满足交换律。那么这题只要所有的数进行
运算,结果就是只出现一次的数。
可推广为数字中,某个元素出现了奇数次,其它元素均出现偶数次,找出出现奇数次的元素。
代码:
impl Solution {
pub fn single_number(nums: Vec<i32>) -> i32 {
nums.iter().fold(0, |acc, e| acc ^ e)
}
}
问题二
给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
示例:
输入: [1,2,1,3,2,5]
输出: [3,5]
思路:类似问题一,如果我们将所有数异或一遍,结果应该是那两个只出现一次的元素设为的异或结果
。那么
表示
二进制之间的差异。公式
结果是只保留
二进制的最后一位 1。所以
的结果(设为变量
)就是
二进制的最后一位差异。那么
或者
,我们据此可以分辨出
,让
与其它出现两次的元素异或,那么就变成只有一个出现一次元素的问题了。结果就是
。则
。
可推广为数字中,某两个元素出现了奇数次,其它元素均出现偶数次,找出出现奇数次的元素。
结合以下代码就很清楚了:
pub fn single_number(nums: Vec<i32>) -> Vec<i32> {
let mut mask = 0;
for num in &nums {
mask ^= num;
}
// 保留最后一位1,这个1要么是x的,要么是y的,假设是x的
let last_one = mask & (mask * -1);
let mut x = 0;
for num in &nums{
// 过滤掉y,就变成了问题一
if num & last_one != 0 {
x ^= num;
}
}
// 找到x, y = mask ^ x
vec![x, mask ^ x]
}
// impl Solution {
// pub fn single_number(nums: Vec<i32>) -> Vec<i32> {
// let mask = nums.iter().fold(0, |acc, n| acc ^ n);
// let last_one = mask & (mask * -1);
// let x = nums.iter().filter(|&&n| n & last_one != 0).fold(0, |acc, n| acc ^ n);
// vec![x, mask ^ x]
// }
// }
问题三
大神题解
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
示例:
输入: [0,1,0,1,0,1,99]
输出: 99
思路:
代码: