数组有哪些算法?
一 概述
将数组算法分为“基础”和“高级”。基础算法:是处理数组必须掌握的核心概念,通常是更复杂算法的构建模块。 高级算法:通常是综合运用多种基础算法和编程技巧(如分治、动态规划等)来解决更复杂的问题。
二 、 基础算法
1 遍历与基本操作
(1) 线性遍历:从头到尾访问每个元素。
(2) 插入/删除元素:在特定位置进行增删操作,涉及元素移动。
(3) 查找极值:寻找数组中的最大值或最小值。
2 核心查找算法
(1) 线性查找:简单粗暴,逐个比较,适用于无序数组。
(2) 二分查找:基础算法中的重中之重。前提是数组有序,通过不断将搜索范围减半来高效定位元素。其各种变体(如找左边界、右边界)也非常重要。
3 经典排序算法
(1) O(n²) 复杂度排序:
冒泡排序:通过相邻元素交换将最大/小值“冒泡”到一端。
选择排序:每次选择剩余元素中的最小/大值,放到正确位置。
插入排序:将元素插入到已排序序列的正确位置,适用于小规模或部分有序数据。
(2) O(n log n) 复杂度排序:
归并排序:分治思想的典型应用。先递归分割,再合并有序子序列。
快速排序:另一种分治思想的典范。选择基准,分区,递归排序。平均性能极佳。
堆排序:利用堆这种数据结构进行排序。
4 双指针技巧
(1) 对撞指针:一左一右两个指针向中间移动。常用于有序数组的求和、判断回文等。
(2)快慢指针:两个指针同向但速度不同。常用于判断循环、寻找中点、原地删除重复元素等。
二、 高级算法
这些算法通常不是单一的步骤,而是一种解决某一类问题的“模式”或“思想”,需要综合运用基础算法。
1 滑动窗口
(1)核心思想:维护一个窗口(子数组),通过移动窗口的左右边界来避免重复计算。常用于求解连续子数组/子串的相关问题。
(2)典型应用:
长度最小的子数组。
无重复字符的最长子串。
字符串的排列。
2 前缀和
(1) 核心思想:预处理数组,构建一个前缀和数组 prefix[i] = arr[0] + arr[1] + ... + arr[i]。从而将区间求和的时间复杂度从 O(n) 优化到 O(1)。
(2)典型应用
快速计算任意区间和。
统计满足条件的子数组个数(常与哈希表结合)。
3 差分数组
(1)核心思想:前缀和的“逆运算”。构建一个差分数组,用于高效地对原始数组的某个区间进行统一的加减操作。
(2)典型应用:
区间批量增加/减少。
航班预订统计、公交车乘客计数等问题。
4 矩阵与二维数组处理
(1)核心思想:将一维数组的算法思想扩展到二维。
(2)典型应用:
螺旋遍历矩阵。
旋转图像(顺时针/逆时针90度)。
在行、列有序的二维矩阵中搜索(可视为二维空间上的“二分查找”)。
5 基于特定思想的算法
(1)摩尔投票法:在 O(n) 时间和 O(1) 空间内找出数组中出现次数超过一半的元素。
(2)洗牌算法:随机打乱数组,保证每种排列的可能性相同。Fisher-Yates 算法是经典实现。
(3)区间合并问题:将重叠的区间合并。
6 融合其他领域的算法
(1) Kadane算法:用于解决最大子数组和问题的动态规划思想。
(2)快速选择算法:基于快速排序的分区思想,在 O(n) 平均时间内找到未排序数组中的第 K 大/小元素。
三 学习建议
(1)首先彻底掌握所有基础算法,尤其是二分查找、快速排序/归并排序和双指针。
(2)然后学习高级算法模式,理解每种模式适用于解决什么问题(例如,看到“连续子数组”要想到滑动窗口或前缀和)。
(3) 最后,通过大量练习,学会识别问题并灵活组合这些基础模块和高级模式来解决问题。
