只出现一次的数字 简单、只出现一次的数字II 中等、只出现一次的数字III 中等
NO.136 只出现一次的数字 简单
思路一:异或
1 | public int singleNumber(int[] nums) { |
时间复杂度:O(n) 空间复杂度:O(1)
NO.137 只出现一次的数字II 中等
思路一:按位统计 遍历数组中每个元素的每一位(除了符号位),统计每一位上 1 的个数,最后再将每一位上 1的数量取模 3,得到最终的结果。例如:
1 | nums[2,2,3,2]=nums[0010,0010,0011,0010] |
不难理解,剩下的就是如何实现。
对每个数字 num 的右移待统计位数,再对 1 求与,可以得到待统计位上的是 1 还是 0。
统计完某一位上 1 的数量之后,取模 3 结果一定是 1 或 0 ,再左移回原本的位上,最后通过异或运算存到结果中。还是上例:
1 | nums[2,2,3,2]=nums[0010,0010,0011,0010] |
1 | public int singleNumber(int[] nums) { |
时间复杂度:O(n) 32次遍历O(32n)。
空间复杂度:O(1)
NO.260 只出现一次的数字III 中等
思路一:分组异或 剑指Offer 第 56 题一样。
如果只有一个数字出现过一次,直接将数组遍历依次异或,最终的到的结果就是只出现过一次的数字。因为异或运算,相同为 0,不同为 1。
但是本题有两个只出现一次的数字 a、b,按照上述方法得到的结果一定是a^b。
如果可以将 nums 分为两组, a 和 b分别再不同的组,其余相同的元素一定在同一个组。这样,我们就可以像开头提到的方法一样,将两组分别异或,两组最后得到的结果,一定就是 a 和 b 。
重点在于如何分组:
- 先将 nums 遍历依次异或,得到 res=a^b。
- 与运算,拿到 res 任意一个等于 1 的位 h。
- 遍历 nums 分别和 h 进行与运算,等于 0 的分一组进行异或,不等于 0 的分一组进行异或,最后两组的结果就是 a 和 b。
1 | public int[] singleNumber(int[] nums) { |
时间复杂度:O(n) 空间复杂度:O(1)
本人菜鸟,有错误请告知,感激不尽!
更多题解和源码:github