1.两数之和

两数之和

这是暴力法中第一次错误的案例
// 两数之和
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range (len(nums)):
            for j in range (len(nums)):
                if target == nums[i] + nums[j]:
                    return [i,j]
                j=j+1
            i=i+1

测试用例
输入[3,2,4] 6
输出[0,0]
预期输出[1,2]

出错原因在于没有考虑相同元素相加为目标数值的情况
且对于for循环理解不够
for index in range(length)
其中index是从0开始循环遍历数组的所有元素,

def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range (len(nums)):
            j=i+1
            for j in range (len(nums)):
                if target == nums[i] + nums[j]:
                    return [i,j]
                j=j+1

如果如上述设置j=i+1作为index,其实它在第二层循环仍是从j=0开始的,所以如果我们想要应用j=i+1开始应该怎么写呢?如下

方法1 用时7444ms
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range (len(nums)):
            for j in range (i+1,len(nums)):
                if target == nums[i] + nums[j]:
                    return [i,j]
                j=j+1
            i=i+1

用for j in range(i+1,len(nums))来表示从i+1到 len(nums)迭代,注意是区间是左闭右开的

其次这里记一下循环中使用else语句的用法:
在 python 中,for … else 表示这样的意思,for 中的语句和普通的没有区别,else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的)的情况下执行,while … else 也是一样。

for num in range(10,20):  # 迭代 1020 之间的数字
   for i in range(2,num): # 根据因子迭代
      if num%i == 0:      # 确定第一个因子
         j=num/i          # 计算第二个因子
         print '%d 等于 %d * %d' % (num,i,j)
         break            # 跳出当前循环
   else:                  # 循环的 else 部分
      print num, '是一个质数'

输出结果:

10 等于 2 * 5
11 是一个质数
12 等于 2 * 6
13 是一个质数
14 等于 2 * 7
15 等于 3 * 5
16 等于 2 * 8
17 是一个质数
18 等于 2 * 9
19 是一个质数
这是利用list相关函数求解

思路是:list.count确保target-num1=num2的存在,其次用list.index函数找出其下标

方法2 用时968ms
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        numslen = len(nums)
        j = -1
        for i in range(numslen):
            if (target - nums[i]) in nums:  # 确保num2在数组中
                if (nums.count(target - nums[i])==1) &(target-nums[i] == nums[i]):  # 当数组中num2只存在一个,且num1=num2时,则找到的这个就是num1本身
                   continue
                else:
                    j=nums.index(target-nums[i],i+1) # 找到num2的下标
                    break
        if j>0:
            return [i,j]
        else:
            return []
方法3 用时412ms

第二种是优化了num2的查找方法

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        lens=len(nums)
        j=-1
        for i in range(lens):
            temp = nums[:i]
            if (target-nums[i]) in temp:
                j = temp.index(target-nums[i])
                break
        if j>=0:
            return [j,i]  #注意这里的返回值是反的
        return []

通过python中diction字典来模拟哈希表查找
方法4 用时44ms
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap={}
        for index,numx in enumerate(nums):
            hashmap[numx]=index  # 注意这里把key和value值反着装是因为下边get函数的应用
        for i,num in enumerate(nums):
            j = hashmap.get(target-num) # python中get函数是 dict.get()=if j is not None and i!=j:  # j即要有定义,又不能是i本身,这样才能避免两个数重复使用
                return [i,j]

这里注意 :
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

Python 2.3. 以上版本可用,2.6 添加 start 参数。

>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
...     print i, element
... 
0 one
1 two
2 three

但是要注意我们方法中的hashmap的应用是反着的,为了下表中get取出

还有一个关键点是 if的条件容易写错,

这种方法是不需要搜索整个字典,只搜索i前的字典即可

方法5 用时56ms
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap={}
        for i,num in enumerate(nums):
            if hashmap.get(target - num) is not None:
                return [hashmap.get(target - num),i]
            hashmap[num] = i #这句不能放在if语句之前,解决list中有重复值或target-num=num的情况


此外 说个题外话

实测三种判断方法运行100万次用时(win10 python3.7.3):

key in dict 用时 1.088 秒
dict.get(key) 用时 1.294 秒
dict[key] 用时 1.01 秒
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值