2018年LeetCode高频算法面试题刷题笔记——只出现一次的数字(开始之前)

1.解答前的碎碎念:

这个系列是写给找工作前的我看的,毕竟作为一个记性很差的人,可能过一段时间又忘了怎么写了。。。然后作为开胃菜的第一题就没有思路,真的是让人非常有挫败感了。。。

2.问题描述:

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

说明:

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

示例 1:

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

示例 2:

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

3.解题思路:

解题思路来源于此链接:https://cuijiahua.com/blog/2018/01/basis_40.html

以下是有用内容的摘录:

大家首先想到的是顺序扫描法,但是这种方法的时间复杂度是O(n^2)。接着大家又会考虑用哈希表的方法,但是空间复杂度不是O(1)。

应该怎么做才能即满足时间复杂度是O(n)又满足空间复杂度是O(1)的要求呢?

我们可以想一想“异或”运算的一个性质,我们直接举例说明。

举例:{2,4,3,6,3,2,5,5}

这个数组中只出现一次的两个数分别是4和6。怎么找到这个两个数字呢?

我们先不看找到俩个的情况,先看这样一个问题,如何在一个数组中找到一个只出现一次的数字呢?比如数组:{4,5,5},唯一一个只出现一次的数字是4。

我们知道异或的一个性质是:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字。比如数组{4,5,5},我们先用数组中的第一个元素4(二进制形式:0100)和数组中的第二个元素5(二进制形式:0101)进行异或操作,0100和0101异或得到0001,用这个得到的元素与数组中的三个元素5(二进制形式:0101)进行异或操作,0001和0101异或得到0100,正好是结果数字4。这是因为数组中相同的元素异或是为0的,因此就只剩下那个不成对的孤苦伶仃元素。

4.相关知识:

位运算小结(按位与、按位或、按位异或、取反、左移、右移):https://blog.csdn.net/mengzhengjie/article/details/80611422

摘录:

按位异或(^)

   参加运算的两个数,换算为二进制(0、1)后,进行异或运算。只有当相应位上的数字不相同时,该为才取1,若相同,即为0。

1

2

3

4

5

6

将10与-10进行按位异或(^)运算:

0000 0000 0000 1010

1111 1111 1111 0110

-----------------------

1111 1111 1111 1100

所以:10 ^ -10 = 1111 1111 1111 1100

   可以看出,任何数与0异或,结果都是其本身。利用异或还可以实现一个很好的交换算法,用于交换两个数,算法如下:

1

2

3

a = a ^ b;

b = b ^ a;

a = a ^ b;

 

5.答案:

class Solution {
public:
    int singleNumber(vector& nums) {
        int result = 0;
        for(int i = 0;i < nums.size();i++)
        {
            result = result ^ nums[i];
        }
        return result;
    }
};

 

你可能感兴趣的:(leetcode刷题笔记)