一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
前言
力扣第136题 只出现一次的数字 如下所示:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
一、思路
题目比较简短,目标就是:找到只出现一次的元素(该元素唯一)。一个朴素的思路如下所示:
- 第一遍遍历数组,给每个元素统计出现的次数
- 再遍历统计的结果,找到出现一次的元素
- 返回该元素即可
根据上面的思路,我实现了一个代码如下图所示:
很显然这种方式虽然能实现,但是击败率一定不会太高。
上面哈希表的方式很明显不能满足题目中不使用额外空间的要求,那么要怎么做呢?
异或运算
下面的思路我也是看了官方题解后自己总结的,根本没有想到使用
异或运算来解题。
异或运算 有如下的三个特点:
- 任何数和 00 做异或运算,结果仍然是原来的数,即
a⊕0=a - 任何数和其自身做异或运算,结果是 0,即
a⊕a=0 - 异或运算满足交换律和结合律,即
a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b
我们知道数组中有且仅有一个不重复的元素,我们不妨假设数组中是这样的内容:ababcb
我们简单的调换一下位置,将一样的放到一起
再将所有元素进行 异或运算 式子为:a⊕a⊕b⊕b⊕b⊕c,计算的过程如下所示:
最终可以得到结果 c。
综上所述: 我们只需要让数组中的所有元素进行异或操作即可,相同的元素会自动消除掉。
二、实现
实现代码
知道了思路后,实现就比较简单了
public int singleNumber(int[] nums) {
int ret = 0; // 初始值0不会对结果有影响
for (int n : nums){
ret = ret ^ n;
}
return ret;
}
测试代码
public static void main(String[] args) {
int[] nums = {4,1,2,1,2};
new Number136().singleNumber(nums);
}
结果
三、总结
今天也算是对 异或运算 有了更深的理解,没想到还能用在寻找单独数字上,真是开了眼界!
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~