【leetcode】LCR177:撞色搭配,数组中数字出现的次数
[TOC]
题目说明
来源:剑指 Offer 56 - I. 数组中数字出现的次数
另外,260只出现以此的数字3这道题和本题是一样的。2023年再回头看,剑指offer在leatcode上改名成lcr了。所以本文标题也更新一下。
难度:中等
一个整型数组 nums
里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
1 | 输入:nums = [4,1,4,6] |
示例 2:
1 | 输入:nums = [1,2,10,4,1,4,3,3] |
限制:2 <= nums.length <= 10000
方法1:常规做法
最容易想到的常规做法:
先对该数组进行qsort排序,再用for循环遍历,找到数组中下标
i
和i+1
不相等的哪一项,这一项i即为只出现了一次的数字。若最末尾的数是目标数,需要进行判断并break,防止越界访问数组
如果你不了解qsort,可以看这篇博客学习一下👉点我
1 | //方法1,太过简单,不够高级 |
方法2:异或求解
复习一下位操作符
很尬尴的是,本人对位操作符和移位操作符并不熟悉。经常把它们记混。几次测试的时候,涉及到这两个操作符的题目就是瞎蒙。
后来发现位操作符和移位操作符似乎是测试中经常考察的对象,这里建议大家一定要把它们弄懂!
语句 | 操作符 | 对应结果 |
---|---|---|
c = a & b | &按位与 | 全1为1,否则0 |
c = a | b | | 按位或 | 有1为1,否则0 |
c = a ^ b | ^按位异或 | 相同为0,不同为1 |
题解
异或有一个特点,a^a=0
,a^0=a
案例1
1 | 输入:nums = [1,2,10,4,1,4,3,3] |
以题目所给参考2为例
1 | 1^2^10^4^1^4^3^3 = 2^10 |
可以看到,当我们把所给数据全部异或在一起的时候,其结果正好是我们需要的两个数相异或。
但是我们好像并没有什么好的办法把已经异或了的两个数拆开
这时候就需要对待查找的数据进行分组
- 分组的目的:让两个单身狗分开到两组数据中
- 这两组数据,除两个单身狗外,其他数字都出现了两次
1 | 1 1 3 3 4 4 2 |
为什么是这么分的呢?
1 | 10: 1010 |
可见单身狗10和2之间,源码第四位才有差别
1 | 1: 0001 |
这时候我们就可以通过第4位的差距,将数据分为两组
第一组是
1~4
,它们的第4位都是0第二组是
10
,只有它的第四位是1
再根据前面异或的特点,对这两组数字进行异或操作,即可得到单生狗10和2
1 | 1^1^3^3^4^4^2 = 2 |
案例2
上面这组数据有些特殊,第二组里面只有10一个数字
我们再来看一组数据
1 | 1 2 3 4 5 1 2 3 4 6 |
这一组数据中,单身狗是5和6
1 | 5:0101 |
可见5和6的源码中,第一、二位都有区别
这里我们取第一位来分类即可
1 | 1:0001 |
二进制第一位为1的数,放入一组
1 | 1 1 3 3 5 |
对它们进行异或操作,就可以得到单身狗5和6
敲代码
1 | //方法2-异或 |
验证
自己整一个main函数来测试一下代码是否能达到要求,成功!
做接口题的时候,如果出现输出错误的情况,可以自己写一个main函数并调试来找出错误
可以看到,运行的用时远远小于方法1的用时
击败了92.9%的用户!
你学会了吗😍
如果这篇博客对你有帮助,点个👍再走呗~
摸鱼之发现另外一道一样的题
1 | class Solution { |