LeetCode Notes_#1 Two Sum

LeetCode Notes_#1 Two Sum

contents

Problem

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Solutions

1. 暴力法
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                tmpSum=nums[i]+nums[j]
                if (tmpSum==target):
                    return [i,j]

时间复杂度:O(n2)

2. 两遍循环哈希表法

关于哈希表(from Wikipedia
散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表
一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名 x 到首字母 F(x) 的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为关键字,“取首字母”是这个例子中散列函数的函数法则 F() ,存放首字母的表对应散列表。关键字和函数法则理论上可以任意确定。

两遍hash表法(Java)
两遍hash表法(Java)

时间复杂度降低为 1242381-20181006185915673-168830907.png

尝试自己使用Python来写一下,事实上Python中的哈希表就是dict数据类型[1]

  • 复述一下dict背后的原理
    为什么要叫做hash map,是因为在每一次向dict里加入新元素时:
#方法1
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']

#方法2
d['Michael']=95

Python会通过对key取hash码,计算得出value的存储位置;
而在访问dict的值的时候:

d['Michael']

同样再进行一次hash运算,这个过程跟之前存储的时候的过程一模一样,但是这样算出来之后就避免了进行循环遍历,将时间复杂度从1242381-20181006185915839-485523722.png降低到1242381-20181006185915981-1267178434.png
但是这也带来了一个限制:dict的key必须是不可变类型,比如说int或者str,不可以是list,因为list是可变的

  • dict的一些方法

    • 使用dict.get('key')来获取响应value,可以避免key不存在而报错
    • 使用in关键字,可以判断某个key是否存在,例如'Thomas' in d,会返回True或者False
    • 使用dict.pop('key')来删除一个键值对
  • 建立一个空字典

#一个是用花括号(我的问题是如何区分set和dict,因为他们都是用{}表示)
d = {}
#另一个是用内置函数dict()
d = dict()
  • 自己写的代码
#自己写的两遍循环哈希表
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        numdict={}#建立空字典
        for i in range(len(nums)):#向字典里添加key:value
            numdict[target-nums[i]]=i
        for j in range(len(nums)):
            if nums[j] in numdict:
                if j!=numdict[nums[j]]:
                    return [j,numdict[nums[j]]]

由于是独立的两个循环,所以时间复杂度是1242381-20181006185916136-511645728.png,上面的方法1是嵌套的两层循环,是1242381-20181006185916387-237756220.png

3. 一遍循环哈希表法

这个其实很简单,就是将上面的两个for循环合并成一个,也就是说,一边向字典添加元素,一边查找之前有没有当前元素的互补数

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        numdict={}
        for i  in range(len(nums)):
            if nums[i] in numdict:
                return [i,numdict[nums[i]]]
            else:
                numdict[target-nums[i]]=i#这一句后执行其实就避免了出现自己和自己相加的情况,避免使用if,else进行判断

ps.要学会使用leetcode自带的playground去调试代码,因为这个是带有测试用例的,而且可以自定义输入


  1. 廖雪峰教程 ↩︎

转载于:https://www.cnblogs.com/Howfars/p/9743366.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值