目录
堆排序 (Heap Sort)
步骤:
时间复杂度:
空间复杂度:
归并排序 (Merge Sort)
步骤:
时间复杂度:
空间复杂度:
二分查找 (Binary Search)
步骤:
时间复杂度:
空间复杂度:
面试中的应用
堆排序 (Heap Sort)
堆排序是一种基于比较的排序技术,利用二叉堆的性质来进行排序。二叉堆可以是最大堆或最小堆,在最大堆中,每个父节点的值都大于或等于其子节点的值,在最小堆中则相反。
步骤:
- 构建堆:将输入的无序数组构建成最大堆或最小堆。
- 排序:
- 在最大堆中,堆顶元素(最大值)与数组最后一个元素交换,然后减小堆的大小,并对新堆进行调整,使其满足最大堆的性质。
- 重复此过程,直到堆的大小为 1。
时间复杂度:
- 构建堆:O(n)
- 调整堆:O(log n)(每次排序)
- 总体:O(n log n)
空间复杂度:
- O(1)(原地排序)
堆排序使用二叉堆来排序一个数组。以下是一个最大堆排序的示例:
#include <iostream>
#include <vector>void heapify(std::vector<int> &arr, int n, int i) {int largest = i; // 初始化最大为根int left = 2 * i + 1; // 左 = 2*i + 1int right = 2 * i + 2; // 右 = 2*i + 2// 如果左子节点大于根if (left < n && arr[left] > arr[largest])largest = left;// 如果右子节点大于最大至此if (right < n && arr[right] > arr[largest])largest = right;// 如果最大不是根if (largest != i) {std::swap(arr[i], arr[largest]);// 递归地定义子堆heapify(arr, n, largest);}
}// 主要的堆排序函数
void heapSort(std::vector<int> &arr) {int n = arr.size();// 构建堆(重新排列数组)for (int i = n / 2 - 1; i >= 0; i--)heapify(arr, n, i);// 一个个从堆顶取出元素for (int i = n - 1; i > 0; i--) {// 移动当前根到结尾std::swap(arr[0], arr[i]);// 调用 max heapify 在减小的堆上heapify(arr, i, 0);}
}// 打印数组元素的函数
void printArray(std::vector<int> &arr) {for (int i : arr)std::cout << i << " ";std::cout << "\n";
}// 测试代码
int main() {std::vector<int> arr = {12, 11, 13, 5, 6, 7};heapSort(arr);std::cout << "Sorted array is \n";printArray(arr);
}
归并排序 (Merge Sort)
归并排序是一种分而治之的算法,通过递归方式将数组分成两半,分别对这两半进行排序,然后合并成一个有序数组。
步骤:
- 分割:将数组从中间分成两半,直到每个子数组只有一个元素或为空。
- 合并:逐步合并子数组,确保每次合并后都是有序的。
时间复杂度:
- O(n log n)(在所有情况下)
空间复杂度:
- O(n)(需要额外的空间来合并数组)
归并排序是一种分而治之的算法,通过将数组分成两半并递归排序,然后合并结果。
#include <iostream>
#include <vector>// 合并两个子数组的函数
void merge(std::vector<int> &arr, int l, int m, int r) {int n1 = m - l + 1;int n2 = r - m;// 创建临时数组std::vector<int> L(n1), R(n2);// 复制数据到临时数组for (int i = 0; i < n1; i++)L[i] = arr[l + i];for (int j = 0; j < n2; j++)R[j] = arr[m + 1 + j];// 合并临时数组int i = 0, j = 0, k = l;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 复制 L[] 的剩余元素while (i < n1) {arr[k] = L[i];i++;k++;}// 复制 R[] 的剩余元素while (j < n2) {arr[k] = R[j];j++;k++;}
}// 主归并排序函数
void mergeSort(std::vector<int> &arr, int l, int r) {if (l >= r) {return; // 如果只有一个元素}int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);merge(arr, l, m, r);
}// 打印数组的函数
void printArray(std::vector<int> &arr) {for (int i : arr)std::cout << i << " ";std::cout << "\n";
}// 测试代码
int main() {std::vector<int> arr = {12, 11, 13, 5, 6, 7};mergeSort(arr, 0, arr.size() - 1);std::cout << "Sorted array is \n";printArray(arr);
}
二分查找 (Binary Search)
二分查找是一种在有序数组中查找特定元素的高效算法。它通过比较数组的中间元素与目标值,来减少搜索范围的一半。
步骤:
- 初始设置:设置两个指针,一个指向数组的起始位置,另一个指向数组的结束位置。
- 循环搜索:在指针指向的范围内,找到中间元素,并与目标值比较:
- 如果中间元素等于目标值,则找到目标,返回其索引。
- 如果中间元素大于目标值,则调整结束指针到中间指针之前。
- 如果中间元素小于目标值,则调整起始指针到中间指针之后。
- 重复:重复步骤 2,直到找到目标或指针重合。
时间复杂度:
- O(log n)
空间复杂度:
- O(1)
二分查找是在已排序数组中查找特定元素的高效方法。
#include <iostream>
#include <vector>// 二分查找函数
int binarySearch(const std::vector<int> &arr, int x) {int l = 0, r = arr.size() - 1;while (l <= r) {int m = l + (r - l) / 2;// 检查元素是否在中间if (arr[m] == x)return m;// 如果元素大于中间,它只可能在右子数组if (arr[m] < x)l = m + 1;// 否则,元素只可能在左子数组elser = m - 1;}// 如果元素不在数组中return -1;
}// 测试代码
int main() {std::vector<int> arr = {2, 3, 4, 10, 40};int x = 10;int result = binarySearch(arr, x);if (result == -1)std::cout << "Element is not present in array";elsestd::cout << "Element is present at index " << result;return 0;
}
面试中的应用
在面试中,你可能不仅要写出这些算法的代码,还需要解释其工作原理和性能特点。对于更高级的面试,你可能需要讨论这些算法的变种,或者在特定情景下如何优化它们。例如,对于堆排序,你可能会被问到如何处理大数据集,或者在归并排序中如何减少内存使用等。