LeetCode高频100题刷题记录之——两数求和

LeetCode高频100题刷题记录之——两数求和

终于开始刷LeetCode了,还没有系统学习过数据结构,导致第一题做出来就很垃圾,只会使用暴力求解,还使用了巨多判断来试图简化计算过程,结果是计算量没有省不说,还严重增加了调试成本。

但是毕竟刚开始,接受自己是个菜鸡的事实也不丢人嘿嘿,因此记录一下用python实现两数求和的过程,包括暴力破解和哈希表查找法,不得不说,哈希表在处理这种问题时真的很有优势,刚刚接触哈希表,后续再不断学习吧!

1 暴力破解法

1.1 思路

做题的时候看到要求尽可能复杂度小于 O ( N 2 ) O(N^2) O(N2),但是暴力破解基本上不可能实现,只能尽可能想办法降低到侠义的 O ( N 2 ) O(N^2) O(N2)以下,其实算法复杂度从大 O O O计算法来说还是 O ( N 2 ) O(N^2) O(N2)

输入:nums: List[int], target: int

输出:result: List[int],预定义result为None

具体思路是:

Step1:判断target是正还是非正;

Step2:构建六个空list,分别存储nums中等于0,等于target,等于target/2,以及根据正负号判断其在不同区间内的nums的索引;

Step3:判断target是否为0,若是,进一步判断nums中为0的数是否有两个,若有,则输出前两个作为result,结束程序;若无,转Step4

Step4:判断是否存在nums中有为0与target的数,若存在,输出这两种情况各自的第一个数的索引作为result,结束程序;若无,转Step5

Step5:判断nums中是否存在有两个以上数值为target/2的数,若存在,则输出符合条件的前两个数的索引为result,结束程序;若不存在,则转Step6

Step6:判断nums中处于①(0, target/2)与②(target/2, target)(target为正)或处于①(target, target/2)与②(target/2, 0)(target为负)的数的存在情况,若①②都存在,遍历两组的数据,若能找到①+②=target的数,取出对应索引,作为result的值,结束程序;若①或②不存在,或者不满足①+②=target,转Step7

Step7:判断nums中处于①(target, +∞)与②(-∞, 0)(target为正)或处于①(-∞, target)与②(0, +∞)(target为负)的数的存在情况,若①②都存在,遍历两组的数据,若能找到①+②=target的数,取出对应索引,作为result的值,若①或②不存在,或者不满足①+②=target,报错,结束程序。

1.2 Python代码

代码可在Leetcode中直接运行。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        result = None
        neg_idx = []    # 存储nums中数值小于0(target为正)或小于target(target为负)的数
        pos_idx = []    # 存储nums中大于target(target为正)或大于0(target为负)的数

        small_idx = []  # 储存nums中大于0但小于target/2的数
        large_idx = []  # 存储nums中大于target/2但小于target的数

        zero_idx = []   # 存储nums中为0的数
        half_idx = []   # 存储nums中为target/2的数
        equal_idx = []  # 存储nums中为target的数

        if target > 0:          # target为正的情况
            for i in range(len(nums)):
                if nums[i] == 0:
                    zero_idx.append(i)
                elif nums[i] == target:
                    equal_idx.append(i)
                elif nums[i] == target/2:
                    half_idx.append(i)
                elif nums[i] < 0:
                    neg_idx.append(i)
                elif nums[i] < target/2:
                    small_idx.append(i)
                elif nums[i] < target:
                    large_idx.append(i)
                else:
                    pos_idx.append(i)
        
        else:  # target <=0的情况
            for j in range(len(nums)):
                if nums[j] == 0:
                    zero_idx.append(j)
                elif nums[j] == target:
                    equal_idx.append(j)
                elif nums[j] == target/2:
                    half_idx.append(j)
                elif nums[j] > 0:
                    pos_idx.append(j)
                elif nums[j] > target/2:
                    large_idx.append(j)
                elif nums[j] > target:
                    small_idx.append(j)
                else:
                    neg_idx.append(j)

        if (target == 0) & (len(zero_idx) >= 2):
            result = [zero_idx[0], zero_idx[1]]
            return result
        elif (len(zero_idx) > 0) & (len(equal_idx) > 0):  # 判断是不是有简单结果1存在
            result = [zero_idx[0], equal_idx[0]]
            return result
        elif len(half_idx) >= 2:
            result = [half_idx[0], half_idx[1]]
            return result
        elif (len(neg_idx) > 0) & (len(pos_idx) > 0):

            for sub_i in neg_idx:
                if result is not None:
                    break

                for sub_j in pos_idx:
                    if nums[sub_i] + nums[sub_j] == target:
                        result = [sub_i, sub_j]
                        break
            if result is not None:
                return result
        if result is None:
            if (len(small_idx) > 0) & (len(large_idx) > 0):
                for sub_i in small_idx:
                    if result is not None:
                        break

                    for sub_j in large_idx:
                        if nums[sub_i] + nums[sub_j] == target:
                            result = [sub_i, sub_j]
                            break
                if result is not None:
                    return result
                else:
                    raise ValueError("数组中没有和为target的两个数!")
            else:
                raise ValueError("数组中没有和为target的两个数!")

1.3 算法评价

判断过程过多,容易出错,过于冗余,虽然理论上可以减少一点计算量,但计算值过多时性能优势不明显。时间复杂度为 O ( N 2 ) O(N^2) O(N2)

2 哈希表实现

2.1 思路分析

计算target与nums的差,再以差为key创建字典,判断时进行索引,方法较为简单,不做算法说明了。

2.2 代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        result = None

        len_nums = range(len(nums))
        keys = [target - nums[i] for i in len_nums]  # 散列函数构造,以target与nums中每个数的差作为key
        nums_dict = dict(zip(keys, len_nums))  # 根据key与值建立对应的哈希表,在python中是字典
        
        for i in len_nums:
            if nums[i] in nums_dict.keys():
                if i != nums_dict[nums[i]]:
                    result = [nums_dict[nums[i]], i]
                    return result
                    break
        if result is None:
            raise ValueError("nums中没有符合条件的两个数!")

对比官方题解,发现我的代码真的太繁琐了,官方的代码非常整洁,真的强。

下面是官方题解,思路值得学习。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for i, num in enumerate(nums):
            if target - num in hashtable:
                return [hashtable[target - num], i]
            hashtable[nums[i]] = i
        return []
    
#  作者:LeetCode-Solution
#  链接:https://leetcode-cn.com/problems/two-sum/solution/liang-shu-zhi-he-by-leetcode-solution/
#  来源:力扣(LeetCode)
#  著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值