二分查找的时间复杂度为:
首先在n个元素中查找, 然后在n/2个元素中查找, 再在n/4个元素中查找...直到为1, 相当于n经过多少次除以2等于1, 所以其时间复杂度为logN
int binarySearch(int arr[], int target, int n) { int left = 0, right = n - 1; while (left <= right) { int pivot = (left + right)/2; if (arr[pivot] == target) return pivot; if (arr[pivot] < target) left = pivot + 1; else right = pivot - 1; } return -1; }
选择排序: 时间复杂度为O(n^2)
/// 选择排序 /// @param arr 数组 /// @param n 数组长度 void selectionSort(int arr[], int n) { int min = 0, tem = 0; for (int i=0; i<n; i++) { min = i; for (int j=i+1; j<n; j++) { if (arr[j] < arr[min]) { min = j; } } if (min != i) { tem = arr[min]; arr[min] = arr[i]; arr[i] = tem; } } }
归并排序: 时间复杂度为O(nlogn)
//合并两个已经排好序的数组 void merge(int array[], int L, int M, int R) { int LEFT_SIZE = M - L; int RIGHT_SIZE = R - M + 1; int left[LEFT_SIZE]; int right[RIGHT_SIZE]; //左边数组填充数据 for (int i=L; i<M; i++) { left[i-L] = array[i]; } //右边数组填充数据 for (int i=M; i<=R; i++) { right[i-M] = array[i]; } int i = 0, j = 0, k = L; //分别从左右两个数组比较数据, 填充到整个数组中 while (i < LEFT_SIZE && j < RIGHT_SIZE) { if (left[i] < right[j]) { array[k] = left[i]; i++; k++; }else { array[k] = right[j]; j++; k++; } } //如果右边数组已经循环完毕, 将左边数组的数据依次填充到数组中 while (i < LEFT_SIZE) { array[k] = left[i]; i++; k++; } //如果做边数组已经循环完毕, 将右边数组的数据依次填充到数组中 while (j < RIGHT_SIZE) { array[k] = right[j]; j++; k++; } } void mergeSort(int arr[], int L, int R) { if (L == R) { return; }else{ int M = (L+R)/2 + 1; mergeSort(arr, L, M - 1); mergeSort(arr, M , R); merge(arr, L, M, R); } }
插入排序: 时间复杂度为O(n^2)
/// 插入排序 /// @param array 要排序的数组 void insertionSort(int array[]) { int i, j, temp; for (i=1; i < sizeof(&array); i++) { for (j=i; j > 0 && array[j] < array[j-1]; j--) { temp = array[j]; array[j] = array[j-1]; array[j-1] = temp; } } }
快速排序:
空间复杂度为O(logN)
/// 快速排序 /// @param array 要排序的数组 /// @param L 数组第0个索引 /// @param R 数组最后一个索引 void quickSort(int array[], int L, int R) { //左侧索引大于右侧索引时直接返回 if (L > R) return; int i = L, j = R, pivot = array[L], temp; //双轴左右索引没有相遇之前, 一直循环移动左右索引遍历 while (L != R) { //右侧索引在没有找到比pivot小的值之前, 一直向左移动, 一直到找到小于pivot的值后, 停下 while (array[j] >= pivot && i < j ) { j --; } //左侧索引在没有找到比pivot大的值之前, 一直向右移动, 一直到找到大于pivot的值后, 停下 while (array[i] <= pivot && i < j) { i++; } //右侧找到比pivot小的值后, 左侧找到比pivot大的值后, 将数组索引为i和j的值进行交换, 同时在左右没有相遇之前保证i小于j if (i < j) { temp = array[i]; array[i] = array[j]; array[j] = temp; } } //左右相遇, i就是pivot的位置, 交换L和i的位置 array[L] = array[i]; array[i] = pivot; //找到pivot的位置后, 然后在pivot左右两侧分别进行快排 quickSort(array, L, i-1); quickSort(array, i+1, R); }
堆排序: 时间复杂度为O(nlogn)
/// 时间复杂度为O(nlogn ) /// 将父节点值和子节点进行比较, 然后将最大值和父节点值进行交换 /// 堆: 满二叉树 && 父节点的值大于子节点 /// i 节点的父节点: parent = (i - 1) / 2 /// i 节点的左节点: c1 = 2 * i + 1 /// i 节点的右节点: c2 = 2 * i + 2 /// 要对第i个节点进行heapify, 先找到第i个节点的两个子节点, 然后进行值比较, 交换 /// @param tree 满二叉树(数组表示 , 从上往下, 从左往右) /// @param n 数组的节点 /// @param i 要对哪个节点进行heapify ( 堆化 ) void heapify(int tree[], int n, int i) { if (i >= n) return; int c1 = 2 * i + 1; int c2 = 2 * i + 2; int max = i; if (c1 < n && tree[c1] > tree[max]) { max = c1; } if (c2 < n && tree[c2] > tree[max]) { max = c2; } if (max != i) { int temp = tree[max]; tree[max] = tree[i]; tree[i] = temp; } } /// 交换数组的两个值 /// @param tree <#tree description#> /// @param i <#i description#> /// @param j <#j description#> void swap(int tree[], int i, int j) { int temp = tree[i]; tree[i] = tree[j]; tree[j] = temp; } /// 构建堆 /// @param tree 表示树的数组 /// @param n 数组的个数 void build_heap(int tree[], int n) { int last_node = n - 1; int parent = (last_node - 1) / 2; int i; for (i = parent; i >= 0; i--) { heapify(tree, n, i); } } /// 堆排序 /// @param tree 表示树的数组 /// @param n 数组的个数 void heap_sort(int tree[], int n) { build_heap(tree, n); int i; for (i = n - 1; i > 0; i--) { swap(tree, i, 0); heapify(tree, i, 0); } }
整形转字符串的时间复杂为:
相当于N经过多少次除以10等于0, 所以其时间复杂度为logN
/** 数字转字符串*/ func intToString(_ num: Int) -> String { var temNum = num var s = "" while temNum>0 { s += "(temNum%10)" temNum /= 10 } s.reversed() return s }
下面的算法的时间复杂度为N*logN
第一层for循环,相当于sz从1开始, 经过多少次乘以2等于n, 或者n经过多少次除以2等于1, 所以第一层的时间复杂度为logN
void hello(int n) { for (int sz = 1; sz < n; sz += sz) { for (int i = 1; i < n; i++) { printf("hello world"); } } }
递归调用求x的n次方的函数的时间复杂度为logN
double pow(int x, int n) { assert( n >= 0); if (value == 0) return 1; double value = pow(x, n/2); if (n%2) { return value*value*x; } return value*value; }
经过2次递归调用的时间复杂度为:
1 + 2 + 4 + 8 = 15
2^0 + 2^1 + 2^2 + 2^3 + ... + 2^n = 2^n+1 -1
int f(int n) { assert(n >= 0); if (n == 0) { return 1; } return f(n-1) + f(n-1); }