每日一练 2020/8/6(python)——两数和

两数和

‘’‘给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
‘’’

一、dictionary 两次循环

def twoSum1(lst, target):
    dic = {} # 创建一个空字典,用来存放索引
    for idx, x in enumerate(lst):
        dic[x] = idx # 把索引放入字典
    for idx, x in enumerate(lst):
        # 如果能在字典里找到相加等于目标值的数
        # 检查两数的值是否相等
        # 1.如果不等,返回两数的索引
        # 2.如果相等,
        # (1)存在多个相同数:遍历时发现的索引是第一个数的索引,字典存的是最后一个的。
        #      返回两数索引  
        #  只需对比两数索引是否相同即可检查是否存在相同的数字
        # (2)两相同的值的索引相同,说明并非是列表里不同的元素,则继续向下查找
        if target - x in dic: 
            if x != target - x:
                return [dic[x], dic[target - x]]
            elif idx != dic[x]:
                return [idx, dic[x]]

二、优化 一次循环

def twoSum2(lst, target):
    dic = {} # 创建一个存放值与索引的字典
    for idx, x in enumerate(lst):
    #如果相加等于目标值的数不存在字典里,则把x添加进去
    #如果相加等于目标值的数在字典里,返回两数的索引
    #这个方法遇到相同的数也不怕
        if target - x in dic:
            return [dic[target - x], idx]
        dic[x] = idx

三、不用字典,硬遍历

def twoSum3(lst, target):
# 从每一个数开始试,后面是否有数可以与其相加得到目标值
    for i in range(len(lst)): 
        for j in range(i+1, len(lst)):
            if lst[i] + lst[j] == target:
                return [i, j]

扩展:三数和

思路:先把数字两两相加,并把索引存入一个字典
遍历整数数组nums,然后在字典中寻找target - x的索引,返回他们的值
实现1:缺点:如果两两相加的结果有重复的,不能完整地放出来

def threeSum(nums, target):
    res = [] # 存放所有结果
    temp = [] # 存放的某一结果
    dSum = {} # 用来存放两两相加的结果、索引
    # 列表中的数两两相加,并存入字典中
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            dSum[nums[i] + nums[j]] = [i, j] 
    # 遍历整数数组nums,然后在字典中寻找target - x的索引,存入res
    for idx, x in enumerate(nums):
        if target - x in dSum and idx not in dSum[target - x]:
            temp = [idx]
            temp.extend(dSum[target - x])
            if set(temp) not in res:
                res.append(set(temp))
    return res   

将所有结果考虑进去后:

def threeSum(nums, target):
    n_w_i= [] # nums_withIndex 
    dSum = {} # 存放能得到这个和的所有的一对数的索引
    all_res = []  # 存放所有的结果
    for idx, val in enumerate(nums):
        n_w_i.append((val, idx)) # 把数值带索引地放到新列表中
    for i in range(len(n_w_i)): # 把两数和以及索引放入字典中
        for j in range(i + 1, len(n_w_i)):
            n_set = set() # 以set的方式存放索引
            n_set.add(n_w_i[i][1]) 
            n_set.add(n_w_i[j][1]) # 两数索引组成的列表
            if n_w_i[i][0] + n_w_i[j][0] not in dSum: # 如果两数和的值不在字典的key中              
                dSum[n_w_i[i][0] + n_w_i[j][0]] = [n_set] # 放入key,以及对应了一个 对应两个索引组成的列表 的一个列表
            elif n_set not in dSum[n_w_i[i][0] + n_w_i[j][0]]:# 如果key存在,如果索引的列表未存进去
                dSum[n_w_i[i][0] + n_w_i[j][0]].append(n_set) # 把索引的列表放入key对应的value中
    for idx, x in enumerate(nums): # 遍历原列表
        if target - x in dSum: # 如果x加上某两数和等于目标,且两数和在字典中
            # 把字典中的所有索引列表与x的索引组合形成新列表(如果x的索引不在索引列表中)放入结果总表中
            for y in dSum[target - x]:
                if idx not in y:
                    a_res = y.copy() # 注意要用copy,不然会出错
                    a_res.add(idx) # 相加等于目标的三个数的索引的列表
                    if a_res not in all_res:
                        all_res.append(a_res)
    return all_res
              

复杂度为O(n^2)

结果对比
在这里插入图片描述

你可能感兴趣的:(每日一练)