[LeetCode-CN]只出现一次的数字

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

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

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

示例 2:

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

思路:
方法一:设置两个指针,一前一后。当两者不等时,后指针后移。当两者相等,则在两个指针位上标记flag,下次不用扫描这两个成员,同时前指针后移,后指针=前指针+1。当后指针遍历完数组仍找不到和前指针相同元素时,前指针元素即为目标。
空间复杂度O(n),因为要建立一个带有标记flag和原有成员的数据结构数组;时间复杂度O(n^2)。
显然,这是最蠢的办法。

方法二:遍历一遍数组,记录最大值max。建立一个有max个元素的bool类型的数组,初值为0。然后再遍历原数组,在原数组的成员的数值所对应编号的bool数组成员上取反。原数组遍历完毕,再遍历bool数组,值为1的元素下标值+1即为目标数值。
局限性很大,若数值大则空间复杂度极高。时间复杂度O(n)。

方法三:拿到题目后隐约感觉要用位运算求解,但是并没有清晰的思路。查阅资料后才知要用异或法求解。
异或,英文为exclusive OR,缩写成xor,是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:
a⊕b = (¬a ∧ b) ∨ (a ∧¬b)
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。
简单来说,就是相同得0,不同得1
运算法则:

  1. a ⊕ a = 0
  2. a ⊕ b = b ⊕ a
  3. a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c;
  4. d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c.
  5. a ⊕ b ⊕ a = b.
  6. a ⊕ 0 = a
    例:若x是二进制数0101,y是二进制数1011,则x⊕y=1110。
    只有在两个比较的位不同时其结果是1,否则结果为0。即“两个输入相同时为0,不同则为1”!

代码:

int singleNumber(int* nums, int numsSize) {
    int a=0;
    for(int i=0;i<numsSize;i++)
    {
        a=a^nums[i];
    }
    return a;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值