LeetCode之路:136. Single Number

一、引言

这是一道非常非常有趣,题目要求非常非常简单,做出来也非常非常容易,但是最优解却非常非常令人无奈的一道题:

Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

大概意思非常简单,我们获得一个整型数组,其中的元素呢,只有一个是单着的,其他都是成双的,让我们找到这个单个的值并返回。

题目要求算法复杂度在线性程度,并且尽量减少额外的存储空间的利用。

这是一道,怎么说呢,看上去非常非常简单,但是想要达到题设要求又比较困难的题目。不如这样,然我们先来探索,能够用什么样的方法来解决这个问题。

二、鄙人不才,想出了两个方法

首先,要找到这个单着的元素,我们需要干什么呢?

比较。

对的,比较,那么找到计数为 1 的不就可以了吗?

于是乎,map 呼之而来:

// use std::map , runtime = 23 ms
class Solution1 {
public:
    int singleNumber(vector<int> &nums) {
        map<int, int> map;
        for (auto i : nums) ++map[i];
        for (auto j : map) if (j.second == 1) return j.first;
    }
};

注释里面的 runtime 是我在 LeetCode 上实跑出来的计时值。

类似的,想到了 map,自然也能想到 set,思路是一样的:

// use std::set , runtime = 25 ms
class Solution2 {
public:
    int singleNumber(vector<int> &nums) {
        set<int> set;
        for (auto i : nums)
            if (set.find(i) == set.end()) set.insert(i);
            else set.erase(i);
            return *set.begin();
    }
};

哈哈,使用 set 反而比使用 map 还要慢,估计是因为 find 方法的缘故吧。

那么问题来了,这两个方法都不是 O(n) 复杂度的算法,并且使用了额外的 nums.size()个存储空间,有什么好的方法呢?

我百思不得其解.
我百思不得其解..
我百思不得其解…

于是乎,点开了 Discuss.
于是乎,点开了 Discuss..
于是乎,点开了 Discuss

三、XOR is always the trick…

看到这个评论,内心是非常戏剧性的:

XOR is always the trick

哈哈哈,又被异或给坑了的感觉油然而生…

让我们看看这段代码:

// use xor , runtime = 13 ms
class Solution3 {
public:
    int singleNumber(vector<int> &nums) {
        int single = 0;
        for (auto i : nums) single ^= i;
        return single;
    }
};

看不懂吧?

没事,有个外国兄弟解释的非常清楚:

For anyone who didn’t understood why this works here is an explanation. This XOR operation works because it’s like XORing all the numbers by itself. So if the array is {2,1,4,5,2,4,1} then it will be like we are performing this operation
((2^2)^(1^1)^(4^4)^(5)) => (0^0^0^5) => 5.
Hence picking the odd one out ( 5 in this case).

看明白了吗?看不懂我来解释解释。

也就是说,我们遍历的时候,循环异或赋值本身,因为
相同为0,不同为1
异或原则,总有一个单着的无法异或掉,前面所有的相同的异或掉只剩下了一堆 0, 而 0 又异或这个单着的值,而又由于在计算机中,非 0 值均为真值,这里自然就返回了不同为真的值 5。

真的非常非常的奇妙!

异或的妙用我已经见了不少了,博客里零零碎碎也记了很多。

最后以那个外国兄弟的感慨结尾:

exactly :) XOR is always the trick

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值