Skip to content

算法时间复杂度

🕒 发布时间:

常见的算法时间复杂度从小到大排序如下:

常数级时间复杂度— O(1)

读取一个固定长度数组中的某个元素,只需要一步操作就能完成,因此时间复杂度为 O(1)

typescript
// 访问数组中的一个元素
const arr: number[] = [1, 2, 3, 4, 5]
const i: number = 2
const x: number = arr[i] // 只需要一步就能完成,时间复杂度为O(1)

对数级时间复杂度— O(log n)

二分查找,每次查找可以将区间缩小一半,因此时间复杂度为 O(log n)

typescript
// 二分查找
function binarySearch(arr: number[], target: number): number {
  let left: number = 0
  let right: number = arr.length - 1
  while (left <= right) {
    const mid: number = Math.floor((left + right) / 2)
    if (arr[mid] === target) {
      return mid
    } else if (arr[mid] < target) {
      left = mid + 1
    } else {
      right = mid - 1
    }
  }
  return -1
}

const arr: number[] = [1, 2, 3, 4, 5]
const target: number = 3
const index: number = binarySearch(arr, target) // 每次查找可以将区间缩小一半,时间复杂度为O(log n)

线性时间复杂度— O(n)

对一个长度为 n 的数组进行线性搜索,最坏情况下需要扫描全部 n 个元素,因此时间复杂度为 O(n)

typescript
// 线性搜索
function linearSearch(arr: number[], target: number): number {
  for (let i: number = 0; i < arr.length; i++) {
    if (arr[i] === target) {
      return i
    }
  }
  return -1
}

const arr: number[] = [1, 2, 3, 4, 5]
const target: number = 3
const index: number = linearSearch(arr, target) // 最坏情况需要扫描全部n个元素,时间复杂度为O(n)

线性对数级时间复杂度 — O(nlogn)

归并排序,可以将一个长度为 n 的数组分成两个长度为 n/2 的子数组,然后递归地将其排序,每轮排序需要进行 O(n) 次操作,因此总的时间复杂度为 O(nlogn)

typescript
// 归并排序
function mergeSort(arr: number[]): number[] {
  if (arr.length <= 1) {
    return arr
  }
  const mid: number = Math.floor(arr.length / 2)
  const left: number[] = arr.slice(0, mid)
  const right: number[] = arr.slice(mid)
  return merge(mergeSort(left), mergeSort(right))
}

function merge(left: number[], right: number[]): number[] {
  const res: number[] = []
  let i: number = 0
  let j: number = 0
  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) {
      res.push(left[i])
      i++
    } else {
      res.push(right[j])
      j++
    }
  }
  while (i < left.length) {
    res.push(left[i])
    i++
  }
  while (j < right.length) {
    res.push(right[j])
    j++
  }
  return res
}

const arr: number[] = [5, 4, 3, 2, 1]
const res: number[] = mergeSort(arr) // 每轮排序需要进行O(n)次操作,总的时间复杂度为O(nlogn)

平方级时间复杂度—O(n^2)

冒泡排序,每次比较相邻两个元素的大小,需要进行 O(n^2) 次比较操作

typescript
// 冒泡排序
function bubbleSort(arr: number[]): number[] {
  for (let i: number = 0; i < arr.length - 1; i++) {
    for (let j: number = 0; j < arr.length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        ;[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
      }
    }
  }
  return arr
}

const arr: number[] = [5, 4, 3, 2, 1]
const res: number[] = bubbleSort(arr) // 需要进行O(n^2)次比较操作,时间复杂度为O(n^2)

立方级时间复杂度— O(n^3)

Floyd 算法,用于计算所有节点之间的最短路径,需要进行 O(n^3) 次计算

typescript
// Floyd算法
function floyd(n: number, graph: number[][]): number[][] {
  const dist: number[][] = graph.slice()
  for (let k: number = 0; k < n; k++) {
    for (let i: number = 0; i < n; i++) {
      for (let j: number = 0; j < n; j++) {
        if (dist[i][j] > dist[i][k] + dist[k][j]) {
          dist[i][j] = dist[i][k] + dist[k][j]
        }
      }
    }
  }
  return dist
}

const graph: number[][] = [
  [0, 3, 8, Infinity, -4],
  [Infinity, 0, Infinity, 1, 7],
  [Infinity, 4, 0, Infinity, Infinity],
  [2, Infinity, -5, 0, Infinity],
  [Infinity, Infinity, Infinity, 6, 0]
]
const res: number[][] = floyd(graph.length, graph) // 需要进行O(n^3)次计算,时间复杂度为O(n^3)

不多项式级时间复杂度 — O(2^n)

汉诺塔问题,需要进行指数级别的计算,因此时间复杂度为 O(2^n)

typescript
// 汉诺塔问题
function hanoi(n: number, from: string, to: string, temp: string): void {
  if (n === 1) {
    console.log(`Move disk 1 from ${from} to ${to}`)
  } else {
    hanoi(n - 1, from, temp, to)
    console.log(`Move disk ${n} from ${from} to ${to}`)
    hanoi(n - 1, temp, to, from)
  }
}

hanoi(3, 'A', 'C', 'B') // 需要进行指数级别的计算,时间复杂度为O(2^n)