接触了代码,那么算法始终是绕不开的一个重点。python
算法对于开发人员,在平常之中的做用很大,可是对于测试人员来讲,实际编码中用到的彷佛不是不少。
不过,如今大厂的测试开发的面试,算法是必考的,并且这也的确是你的代码功底的一项重要体现,学学没坏处。面试
关于算法的基础知识,以前本身也买过书,可是学习的断断续续的,练习刷题就更加稀少了。
因此,打算往后作一个【简单算法】的记录:算法
题目来自LeetCode传送门,有兴趣的童鞋能够到上面刷题练习。数组
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。函数
你能够假设每种输入只会对应一个答案。可是,数组中同一个元素不能使用两遍。学习
给定 nums = [2, 7, 11, 15], target = 9 由于 nums[0] + nums[1] = 2 + 7 = 9 因此返回 [0, 1]
忽然有了考试作题的感受,我以为首先题目要先审清楚,而后本身尝试用本身已有的知识去解决。
实在作不出来,也别泄气,算法道路必定是曲折的,起码对我来讲是这样,大佬除外。测试
另外,无论作不作出来,都要去学习下示例解法,学习解题思路,从中收获更多。编码
我本身尝试着作,这题由于属于简单难度,我用for循环的知识进行了暴力破解,代码以python3为例:code
def twoSum(nums, target): for i in range(len(nums)): for j in range(i+1, len(nums)): if nums[i] + nums[j] == target: return [i, j]
其实就是2次循环,最外层的循环,从列表第一个开始遍历,直到最后一个元素,长度就是len(nums)
。
由于题目中说,单元素不能使用两次,因此内层的循环,就从i 以后也就是i+1
开始,直到最后一个元素。blog
拿到了2个数,就进行相加操做,与target
进行比较,若是相等,就返回出这2个元素的下标。
运行一下:
def twoSum(nums, target): for i in range(len(nums)): for j in range(i+1, len(nums)): if nums[i] + nums[j] == target: return [i, j] if __name__ == "__main__": print(twoSum2([2, 15, 11, 7], 9)) -------------结果---------------------- D:\Programs\Python\Python36\python.exe D:/练习/leecode/two_sum.py [0, 3] Process finished with exit code 0
这题虽然我作出来,可是这个解法并很差,若是遇到一个元素不少的列表,而且最后的2个值 之和 等于目标值,那么这种状况下,
数组里的任意2个元素都要匹配比较一次。
时间复杂度就为:O(N^2)。
空间复杂度还好,由于没去去开辟额外的空间去计算,因此是:O(1)。
关于复杂度的分析,后面单独写一篇介绍。
上面的解法缺点就是在最坏的时候,数组里的任意2个元素都要匹配比较一次,那么就要来解决这个问题。
换个思路来想,遍历列表的中的元素x,若是列表中存在 target-x
,那么这2个数的下标就是最终咱们要的结果。
官方的建议解法用了哈希表,对于key-value这样的存储形式,x
跟它的下标是对应的,这样一来,找到target-x
的时间复杂度就变成了O(1)。
因此新的解法就是:
def twoSum2(nums, target): hashtable = dict() for i, num in enumerate(nums): if target - num in hashtable: return [hashtable[target - num], i] hashtable[nums[i]] = i return []
这里使用python,能够建立一个空字典。再利用python中的enumerate()
函数,遍历出列表里的元素和下标。
在每一次的遍历中,就能够用目标值 target
—— 当前元素 num
,判断这个值 在不在字典里。
这里用到的是Python 字典 in 操做符,用于判断键是否存在于字典中。
若是在的话,那就返回 字典里的 元素以及,下标。
由于刚开始循环的的时候,字典里没数据,因此当每次循环后,咱们要把此次循环的元素跟它的下标 分别 做为 key和value放到字典里去。
能够加个打印看下 字典的操做过程:
def twoSum2(nums, target): hashtable = dict() for i, num in enumerate(nums): if target - num in hashtable: return [hashtable[target - num], i] hashtable[nums[i]] = i print(hashtable) return [] if __name__ == "__main__": print(twoSum2([4, 15, 3, 7, 2], 9)) =============================结果============================== D:\Programs\Python\Python36\python.exe D:/练习/leecode/two_sum.py {4: 0} {4: 0, 15: 1} {4: 0, 15: 1, 3: 2} {4: 0, 15: 1, 3: 2, 7: 3} [3, 4] Process finished with exit code 0
最终,分析解法2的复杂度:
时间复杂度—— O(N),N 是列表中的元素数量。对于每个元素 x,咱们能够 O(1) 地寻找 target - x。
空间复杂度—— O(N),其中 N 是数组中的元素数量。主要是哈希表的开销,在空间上的消耗。
其实也不能说解法1就是最烂的,由于算法没有最好的算法,只有最适合的算法。
随着需求在空间和时间的取舍的不一样,具体决定使用哪一种算法也是不一样的。
在这个简单算法里,学习和回顾到的知识点: