基本概念:
Time complexity时间复杂度:
时间复杂度是指当输入大小增加时,运行算法所需的时间。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度(O是数量级的符号 ),简称时间复杂度。
几种常见的时间复杂度:
T(n) = O(1)恒定时间
//MARK: Constant time恒定时间 T(n) = O(1)
// 恒定时间算法是一个不在乎输入大小但运行时间相同
**func** constantTimeAlgorithm(names: [String]) -> Void {
// if let fisrt = names.first 语句执行1次
if let first = names.first {
// print函数属性1次
print(first)
// else执行1次 通常else不进入统计 因为else后面不需要接任何我们书写的代码
} else {
// print函数执行1次
print("Not value")
}
// 得到的总次数是3 T(n) = O(3) 根据同数量级函数的定义化简为 T(n) = O(1)
}
T(n) = O(n)线性时间
//MARK: Linear time线性时间 T(n) = O(n)
// 随着数量的增加循环的迭代次数也会相应的增加
func linearTimeAlgorithm(names:[String]) -> Void {
// for name in names执行 names.count次数 次数可变设为n
for name in names {
// print函数执行names.count次数 次数可变设为n
print(name)
}// 得到的总次数就是2n 根据同数量级函数 T(n) = O(n) 因为2n/n = 2 所以O(2n)化简为O(n)
}
T(n) = O(n^2)二次平方时间
//MARK: Quedratic time二次平方时间 T(n) = O(n^2)
// 通俗说就是循环嵌套循环,算法时间复杂度大约就是输入大小的平方
func quadraticTime(names:[String]) {
// 外层的遍历执行n次 这里n代表names.count-1
for _ in names {
// 外层每遍历1次 这里就是n次,所以总共算下来内部for name in names就执行了n^2
for name in names {
// print函数也是执行了n^2次
print(name)
}
}
// 总共执行了n + n^2 + n^2 = 2n^2 + n 同数量级化简之后 T(n) = O(n^2)
}
T(n) = O(log2(n))对数时间
//MARK: Logarthmic time (对数) T(n) = O(log2(n))**
/**
展示对数时间复杂度的算法形式
- **parameter** value: 需要匹配的值
- **parameter** array: 一个无需数组
*/
func logarithmicTime(_ value: Int, in array:[Int]) -> Bool {
// 执行1次
if array.isEmpty {
// 执行1次或者0次
return false
}
// 数组从大到小排列 执行1次
let sortedArr = array.sorted(by: >)
//各1次
var startedIndex = 0
var endIndex = array.count - 1
var middleIndex = (startedIndex + endIndex)/2
repeat {
if sortedArr[middleIndex] > value {
startedIndex = middleIndex + 1
// middleIndex = (startedIndex + endIndex)/2
// 使用位移表示除以2
middleIndex = (startedIndex + endIndex)>>1
}
else if sortedArr[middleIndex] < value {
endIndex = middleIndex - 1
middleIndex = (startedIndex + endIndex)/2
}
else {
// 相等
print("find the element in sorted array and index is\(middleIndex)")
return true
}
}while (startedIndex <= endIndex)
//最多会执行t次 其中 startedIndex* 2^t = endIndex => t = log2(endIndex/startedIndex)
repeat中的执行总数和while相同 所以最后的结果化简后就是O(log2(n))
return false
}
T(n) = O(n*log2(n))拟线性时间
//**MARK: Quasilinear time 拟线性时间 T(n) = O(n*log2(n))**
/**
展示拟线性算法,内部调用了对数时间复杂的二分查找算法
- **parameter** sourcaArray: 源数组 。查找该数组中的每个元素是否·存在于destinationArray
*/
func qualilinearTime(source sourceArray:[Int], destination destinationArray:[Int])-> Bool {
//destination排序 从大到小
let sortedArr = destinationArray.sorted(by: >)
// 外层循环执行n次 其中n = sourceArray.count
for outsideIndex in 0..<sourceArray.count {
// 此函数一共执行n*log2(n)次
logarithmicTime(sortedArr[outsideIndex], in: destinationArray)
}
//执行1次
// 最后总的时间复杂度就是T(n) = O(n*log2(n))
return false
}
space complexity空间复杂度:
时间复杂度算法帮助预测扩展性,但他不是唯一的衡量标准 空间复杂度是衡量算法运行时所需的资源。对于计算机来说算法资源就是内存。
//MARK: 线性空间复杂度 O(n)
func printSorted(_ array:[Int]) {
let sorted = array.sorted()
//这里实际上创建了n个element对象 所以空间复杂度是O(n)
for element in sorted {
print(element)
}
}
// 其余均类似于时间复杂度的统计方式 创建一个变量就统计一次。其余标准空间复杂度不再赘述