数据结构(data-structure)和算法(algorithm)二
算法时间度量指标
通过上一部分的讲解,我们知道了评判代码的优劣程度的实现是通过的是我们的算法复杂度来评价的
然后呐这个算法复杂度的计算的话就是通过的是我们的赋值次数来初步评判的
T(n) = 1 + N
总时间 = 赋值语句(常量) + N(问题规模)
算法时间 —— 大O表示法
- 常数时间复杂度(O(1) ): 表示的就是无论问题规模是多少,算法的执行时间都是固定的,例如:直接访问数组中的某个元素
- 线性时间复杂度(O(n) ):表示的就是算法的执行时间合问题规模是成线性相关的,例如:遍历一个数组或者链表
- 对数时间复杂度(O(log n) ):表示的就是算法执行时间合问题规模成对数关系,例如:二分法查找算法
- 平均时间复杂度(O(n ^ 2) ):表示的就是算法的执行时间合问题规模的平方成关系,例如:冒泡排序
- 最坏时间复杂度(O(n ^ 3) ):表示的就是算法在最坏情况下的执行时间合问题规模的立法成正比
- 最好时间复杂度(O(1) ):表示的就是算法在最好的情况下的执行时间是常数,即无论问题规模有多大,算法执行时间固定
通过上面的了解的话,我们能够实现代码的优化的工作就是将我们的代码的时间复杂度尽量往常数时间复杂度来靠近
这个就是我们的最终的书写代码的需要考虑的方向性(理论来说是这样的,尽量往这个方向靠!!! )
时间复杂度的排比的话就是: o(1) > o(n) > o(log n) > o(n ^ 2) > o(n ^ 3)
算法问题 —— 变换词问题
就是我们输入一个单词,但是不考虑字符的位置因素,只要是相同的一些字符组成那就是两个字符相同相等
abcd == cdba
abc != bcad也就是说这种题目的意思是:字符个数相同,字符组成相同,那么最后两个单词就是同一个单词了
通过转化为列表并且排序,然后一一比对实现判断
# python 实现的该算法解决问题
import time
# 开始书写一个工具函数来实现判断我们的算法的运行时间
def get_time(fn):
def run(word01, word02, *args, **kwargs):
start_time = time.time()
res = fn(word01, word02, *args, **kwargs)
run_time = time.time() - start_time
print("函数运行时间为: %10.15f" % run_time)
print("匹配结果为{}".format(res))
return run
@get_time
def word_match(word01, word02, *args, **kwargs):
if len(word01) != len(word02):
return False
# 首先先将字符转化为列表
word_list01 = list(word01)
word_list02 = list(word02)
# 然后进行列表中的字符排序,然后一一比对即可
word_list01.sort()
word_list02.sort()
# 然后进行比对即可
index = 0
match_cursor = True
while index < len(word01) and match_cursor:
# 开始遍历比对每一个下标是否相等
if word_list01[index] == word_list02[index]:
index += 1
else:
match_cursor = False
print(index)
break
return match_cursor
word_match("abcd", "bcd") # False 0.000000000000000
word_match("abcd", "bcad") # True 0.000000000000000
"""
通过分析,我们的程序的时间复杂度为:
T = 1 + 1 + N
但是我们的 sort 函数实际上的话,也是具备一定的时间复杂度的
其内层机制的话就是使用了我们的冒泡排序, log n
所以说其算法时间复杂度为: o(log n)
"""
// JavaScript 实现该算法的解决问题
function word_match(word01, word02, ...args) {
// 边界判断
if (word01.length !== word02.length) {
return false
}
word01 = word01.split('').sort()
word02 = word02.split('').sort()
console.log(word01, word02)
let index = 0
let match_cursor = true
while (index < word01.length && match_cursor) {
if (word01[index] === word02[index]) {
index += 1
}
else {
match_cursor = false
break
}
}
return match_cursor
}
console.log(`匹配结果为 ${word_match("abcd", "bacd")}`) // 匹配结果为 true
使用 ASCII 码进行比对
这个时候,我们就不需要进行使用 sort() 内置的冒泡排序了,直接记录即可
import time
# 开始书写一个工具函数来实现判断我们的算法的运行时间
def get_time(fn):
def run(word01, word02, *args, **kwargs):
start_time = time.time()
res = fn(word01, word02, *args, **kwargs)
run_time = time.time() - start_time
print("函数运行时间为: %10.15f" % run_time)
print("匹配结果为{}".format(res))
return run
@get_time
def word_match(word01, word02, *args, **kwargs):
# 边界判断
if len(word01) != len(word02):
return False
# 创建两个列表分别记录字母出现的位置
list01 = [0] * 26 # N
list02 = [0] * 26 # N
# 对第一个进行判断的字符进行处理操作
for i in range(len(word01)): # N
index = ord(word01[i]) - ord("a")
list01[index] = list01[index] + 1
# 对第二个进行判断的字符进行处理操作
for i in range(len(word02)): # N
index = ord(word01[i]) - ord("a")
list02[index] = list02[index] + 1
index = 0
match_cursor = True
while match_cursor and index < len(list01): # N
if list01[index] == list02[index]:
index += 1
else:
match_cursor = False
return match_cursor
word_match("abcd", "bcd") # False
word_match("abcd", "bcad") # True
"""
这个时候的时间复杂度就是: T = 5N ==> T = N ==> o(N)
"""