LINTCODE:136 只出现一次的数字(Python语言实现)

1. 题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:

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

示例 2:

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

2. 使用列表

        首先考虑到使用列表的数据结构,因为append方法每次的操作均为常数级的操作。但在检索的过程中,in方法仍是线性级别的,导致运行结果为“超出时间限制”。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sn = []
        for nu in nums:
            if nu not in sn:
                sn.append(nu)
            else:
                sn.remove(nu)
        return sn[0]

3. 使用字典

        列表的in方法采用的仍是遍历的过程,此时会想到字典这个数据结构。生成键-值对,其中关键字作为键,出现次数为值。使用keys方法就可以轻松的得到键的可迭代对象,这样对关键字的检索就是常数级了。在这里,输出使用的pop方法,输入采用的基本赋值。经测试显示“通过”。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sd = {}
        for nu in nums:
            if nu in sd.keys():
                sd.pop(nu)
            else:
                sd[nu] = 1
        return list(sd.keys())[0]

        需要注意的地方是:当字典中的键值需要导出的时候,使用keys方法得到的是可迭代对象,所以用list方法列表化

4.  使用集合

        集合的思想就是简化出来字典的“键”,在这里,输入采用的add方法,输出采用的remove方法。返回值的int类型采用的pop方法。平台上测试的结果,是“通过”,但要比使用字典的数据结构要慢。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sd = set()
        for nu in nums:
            if nu in sd:
                sd.remove(nu)
            else:
                sd.add(nu)
        return sd.pop()

5. 如何不使用额外空间实现?

        时间复杂度的线性级别很容易采用数据结构的特性来弥补,但空间复杂度的常数级,也就意味着只能使用数个中间变量作为中转来实现。

        首先想到的是加减操作,但运算符的判定是要建立在有序数组的基础上。所以可以采用先排序,再设置标志位flag进行加减的操作。函数sorted()采用的是就地操作,一定程度上也算是没有添加额外的辅助空间。经测试,显示“通过”。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sn, flag = 0, True
        for nu in sorted(nums):
            if flag:
                sn += nu
                flag = False
            else:
                sn -= nu
                flag = True
        return sn

        那有没真正意思上的不使用额外空间的线性级别的算法呢?是有的,这里是借助异或运算符的魔法。异或运算符在二进制的位数上,相同则为0,不同为1,常用于不设置中间变量传递值就交换两个数。

        在这里,异或运算符的经典之处,在于存储二进制各位上的状态值。相同的情况下就会抵消,留出来的就是单个的。比如:

数组:【1, 3, 2, 1, 2】

1:0 0 1

3:1 0 1    

2:0 1 0

1:0 0 1

2:0 1 0

        竖向看的话,明显的相互抵消,尽管有先后顺序,但值并没有发生变化。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sn = 0
        for nu in nums:
            sn ^= nu
        return sn

(最近更新:2018年10月18日)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值