矩阵操作优化:从 O(q×n) 到 O(q) 的优雅进阶

最近在刷题时遇到一个很有意思的矩阵操作问题:给定一个 m×n 的矩阵,初始按行优先顺序填充 1 到 m×n,然后有 q 个查询,每个查询可能是交换两行、交换两列,或者打印某个位置的元素。

乍一看这题很简单,直接模拟就行,但仔细想想,如果矩阵很大、查询很多,暴力模拟的效率其实并不高。今天就来聊聊两种解法,看看怎么从 O(q×n) 优化到 O(q)。

问题描述

给定两个整数 m 和 n,表示矩阵的维度。矩阵初始按行优先顺序填充 1 到 m×n。同时给定一个 2D 数组 queries,每个查询格式为 [t, x, y]:

  • t=1:交换第 x 行和第 y 行
  • t=2:交换第 x 列和第 y 列
  • t=3:打印位置 (x, y) 的元素

示例:

输入:m=3, n=3

queries = [[1, 0, 1], [3, 0, 0], [3, 1, 0], [2, 0, 1], [3, 0, 0], [3, 1, 0]]

输出:[4, 1, 5, 2]

初始矩阵:

复制代码
1 2 3
4 5 6
7 8 9

操作过程:

  1. 交换行 0 和行 1 → 矩阵变为:

    4 5 6
    1 2 3
    7 8 9

  2. 打印 (0,0) → 4

  3. 打印 (1,0) → 1

  4. 交换列 0 和列 1 → 矩阵变为:

    5 4 6
    2 1 3
    8 7 9

  5. 打印 (0,0) → 5

  6. 打印 (1,0) → 2

搞懂矩阵操作从 O(q×n) 优化到 O(q) 的优雅思路,光看公式推导容易绕进去。不如试试 图码 这个宝藏网站,它用交互式动画把60多种算法和数据结构讲得一清二楚,比如矩阵链乘、动态规划这些难点,都能拖拽输入自定义数据或上传C/C++/Java/Python代码自动生成可视化过程。特别适合备战 408考研 和高校 数据结构期末考试 ,每个知识点都配了全书级的详解和可运行代码。最近复习遇到瓶颈,直接去 图码 看动画,真的一下就通了。

图码-数据结构与算法交互式可视化平台

访问网站:https://totuma.cn

解法一:暴力模拟(Naive Approach)

最直接的想法就是真的去创建一个矩阵,然后每次交换操作都去遍历整行或整列进行元素交换。

核心代码:

python 复制代码
def swapRows(mat, r1, r2):
    for i in range(len(mat[0])):
        mat[r1][i], mat[r2][i] = mat[r2][i], mat[r1][i]

def swapCols(mat, c1, c2):
    for i in range(len(mat)):
        mat[i][c1], mat[i][c2] = mat[i][c2], mat[i][c1]

def solveQueries(m, n, query):
    mat = [[(i * n) + j + 1 for j in range(n)] for i in range(m)]
    for q in query:
        if q[0] == 1:
            swapRows(mat, q[1], q[2])
        elif q[0] == 2:
            swapCols(mat, q[1], q[2])
        else:
            print(mat[q[1]][q[2]], end=" ")

复杂度分析:

  • 时间复杂度:O(q × n)(每次交换行/列需要遍历 n 个元素)
  • 空间复杂度:O(m × n)

当 m 和 n 很大时,这个复杂度显然不够理想。

解法二:辅助数组法(Expected Approach)

仔细想想,我们真的需要每次都去修改矩阵吗?其实矩阵中的每个元素都可以通过公式计算出来:

mat[x][y] = (n × x) + y + 1

如果我们能记录下每次交换操作对行和列的影响,那么查询时直接根据公式计算即可!

具体做法是用两个辅助数组 rows[m] 和 cols[n],分别记录当前第 i 行/列对应的是原始矩阵中的哪一行/列。

  • rows[i] 表示当前第 i 行对应原始矩阵的第 rows[i] 行
  • cols[j] 表示当前第 j 列对应原始矩阵的第 cols[j] 列

交换行时,只需要交换 rows 数组中的两个元素;交换列时,只需要交换 cols 数组中的两个元素。

查询位置 (x, y) 时,实际元素为:
mat[rows[x]][cols[y]] = (rows[x] × n) + cols[y] + 1

核心代码:

python 复制代码
def solveQueries(m, n, query):
    rows = [i for i in range(m)]
    cols = [i for i in range(n)]
    for q in query:
        if q[0] == 1:
            rows[q[1]], rows[q[2]] = rows[q[2]], rows[q[1]]
        elif q[0] == 2:
            cols[q[1]], cols[q[2]] = cols[q[2]], cols[q[1]]
        else:
            print((rows[q[1]] * n) + cols[q[2]] + 1, end=" ")

复杂度分析:

  • 时间复杂度:O(q)(每次操作都是 O(1))
  • 空间复杂度:O(m + n)

总结

方法 时间复杂度 空间复杂度
暴力模拟 O(q × n) O(m × n)
辅助数组 O(q) O(m + n)

这个优化思路其实很巧妙:通过记录映射关系来避免实际的数据移动,从而将每次操作从 O(n) 降到 O(1)。这种思想在很多场景下都适用,比如处理大量交换操作的问题时,可以优先考虑是否能用映射关系来优化。

希望这篇文章对你有帮助!如果你有其他优化思路,欢迎在评论区讨论~

相关推荐
YL200404262 小时前
046二叉树展开为链表
数据结构·leetcode·链表
代码无bug抓狂人2 小时前
二分法——方程求解
算法·数学建模
蝈理塘(/_\)大怨种2 小时前
快速排序的三路划分和自省排序
数据结构·算法
qq_296553272 小时前
矩阵转置的两种实现方式:从暴力法到原地算法
数据结构·线性代数·算法·青少年编程·矩阵
2zcode2 小时前
滚压表面强化过程中变形诱导位错演化与梯度晶粒细化机理的数值模拟研究
人工智能·python·算法
渣渣苏2 小时前
硬核拆解 HNSW:亿级向量如何实现毫秒级召回?(下篇:实战调参与工程优化)
人工智能·算法·agent·向量数据库·hnsw·智能体
Felven3 小时前
A. Candies for Nephews
算法