LeetCode.1 Two Sum

LeetCode编程题大名鼎鼎,百闻不如一作。就像开始学习一门新的编程语言时,都会先尝试实现hello world一样,LeetCode也为同学准备了一系列入门的题型。今天就为大家试水一下新手第一题Two Sum

题目简述

给定一个随机整型列表,返回两个数的序号,使得它们的和等于给定的目标数。题目假设返回的结果是唯一的,当没有满足的解时返回空值即可。

解法一:暴力求解

每个人最先想到都是暴力求解,对列表中的每一个数,分别和其后面的数相加判断是否等于给定的目标数。

​
class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        n = len(nums)
        for i in range(n):
            a = nums[i]
            for j in range(i+1, n):
                b = nums[j]
                if a + b == target:
                    return [i, j]

​

考虑一种较差的情况,列表中不存在满足条件的解,那么算法需要运行n\times{n-1}次。线上测试时间为6504ms,因为有很大概率需要遍历列表中的所有数字,自然结果不如人意。

解法二:前向匹配

对列表中的每一个数,和序号在它前面的数进行匹配。具体的实现中用一个字典存放遍历过的数,遍历到一个新的数,从字典中搜索是否存在一个数满足两者相加等于目标值。

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        d = {}
        for j in range(len(nums):
            try:
                for k in d.keys():
                    if d[k] == target - nums[j]:
                        return [k, j]
                d[j] = nums[j]
            except Exception as e:
                raise

解法二在实现上依旧存在缺陷,字典d中的键值为数字在列表中的序号,这导致每次需要展开一个循环去匹配键值。线上测试时间为3152ms。对上述代码最直接的改进便是利用数字作为字典的键值,充分利用python3字典自带的__getitem__()函数。但是字典的键值通常是唯一的,相同的数字会覆盖前者。在本题中,由于采用的是向前匹配,如果存在一种输入,列表为1213,目标值为4时,这时解不是唯一的。以上情况是和题意不符的,可以不以考虑。

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        d = {}
        for i in range(len(nums)):
            if target - nums[i] in d:
                return [d[target - nums[i]], i]
            else:
                d[nums[i]] = i

改进后的解法线上测试大致在30~40ms。

总结

python3的效率还是低了点,有兴趣的同学可以尝试使用c/c++或者java,应该用时会比较短。第一次写technology blog,有什么不足请多多谅解。

猜你喜欢

转载自blog.csdn.net/qq_30818049/article/details/82891682