用100道题拿下你的算法面试(矩阵篇-2):求转置矩阵

一、面试问题

给定一个二维矩阵 mat [][],计算其转置矩阵。矩阵的转置是通过将原矩阵的所有行转换为列、所有列转换为行得到的。

示例 1:

  • 输入以下矩阵:

    mat[][] = [
    [1, 1, 1, 1],
    [2, 2, 2, 2],
    [3, 3, 3, 3],
    [4, 4, 4, 4]
    ]

  • 得到以下输出:

    [
    [1, 2, 3 ,4],
    [1, 2, 3, 4],
    [1, 2, 3, 4],
    [1, 2, 3, 4]
    ]

  • 解释如下:

输出为输入矩阵的转置,其中每一行变为一列。该重排方式使得原矩阵中的竖直模式在结果中变为水平模式。

示例 2:

  • 输入以下矩阵:

    mat[][] = [
    [1, 2],
    [9, -2]
    ]

  • 得到以下输出:

    [
    [1, 9],
    [2, -2]
    ]

  • 解释如下:

输出为输入矩阵的转置,其中每一行变为一列。该重排方式使得原矩阵中的竖直模式在结果中变为水平模式。

二、【解法一】暴力法求解矩阵转置 ------ 时间复杂度 O (m*n),空间复杂度 O (m*n)

(一) 解法思路

该思路是创建一个新矩阵,通过交换索引将原矩阵的行转换为列 ------ 原矩阵中位置 [i][j] 上的元素,在转置矩阵中变为 [j][i]。

逐步骤实现:

  • 初始化一个大小为 m × n 的新矩阵(行列互换)。
  • 遍历原矩阵的每一个元素。
  • 将原矩阵中第 r 行第 c 列的每个元素,赋值给新矩阵中第 c 行第 r 列的位置。
  • 返回新的转置矩阵。

(二) 使用 5 种语言实现

1. C++

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

vector<vector<int>> transpose(vector<vector<int>>& mat) {

    int rows = mat.size();        
    int cols = mat[0].size();    

    // 创建一个 cols 行 rows 列的结果矩阵,用于存储转置矩阵
    vector<vector<int>> tMat(cols, vector<int>(rows));

    // 通过将行与列互换,填充转置矩阵
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {

            // 赋值转置后的值
            tMat[j][i] = mat[i][j];  
        }
    }

    return tMat;  
}

int main() {
    vector<vector<int>> mat = {
    {1, 1, 1, 1},
    {2, 2, 2, 2},
    {3, 3, 3, 3},
    {4, 4, 4, 4}
};

    vector<vector<int>> res = transpose(mat);


    for (auto& row : res) {
        for (auto& elem : row) {
            cout << elem << ' ';  
        }
        cout << "\n";  
    }

    return 0;
}

2. Java

java 复制代码
import java.util.ArrayList;
import java.util.Scanner;

public class DSA {

    public static ArrayList<ArrayList<Integer>>
    transpose(int[][] mat) {

        int rows = mat.length;           
        int cols = mat[0].length;        

        // 创建一个 cols 行 rows 列的结果矩阵,用于存储转置矩阵
        ArrayList<ArrayList<Integer>> tMat = new ArrayList<>();

        // 通过将行与列互换,填充转置矩阵
        for (int i = 0; i < cols; i++) {
            ArrayList<Integer> row = new ArrayList<>();
            for (int j = 0; j < rows; j++) {
                // 赋值转置后的值
                row.add(mat[j][i]);  
            }
            tMat.add(row);
        }

        return tMat;
    }

    public static void main(String[] args) {

        int[][] mat = {
            {1, 1, 1, 1},
            {2, 2, 2, 2},
            {3, 3, 3, 3},
            {4, 4, 4, 4}
        };

        ArrayList<ArrayList<Integer>> res = transpose(mat);

        for (ArrayList<Integer> row : res) {
            for (int elem : row) {
                System.out.print(elem + " ");
            }
            System.out.println();
        }
    }
}

3. Python

python 复制代码
def transpose(mat):
    rows = len(mat)             
    cols = len(mat[0])         

    # 创建一个 cols 行 rows 列的结果矩阵,用于存储转置矩阵
    tMat = [[0 for _ in range(rows)] for _ in range(cols)]

    # 通过将行与列互换,填充转置矩阵
    for i in range(rows):
        for j in range(cols):
            
            # 赋值转置后的值
            tMat[j][i] = mat[i][j]

    return tMat

if __name__ == "__main__":
    mat = [[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3], [4, 4, 4, 4]]

    res = transpose(mat)

    for row in res:
        for elem in row:
            print(elem, end=' ')
        print()

4. C#

cs 复制代码
using System;
using System.Collections.Generic;

public class DSA {
    public static List<List<int>> transpose(int[,] mat) {
        int rows = mat.GetLength(0);    
        int cols = mat.GetLength(1);   

        // 创建一个 cols 行 rows 列的结果矩阵,用于存储转置矩阵
        List<List<int>> tMat = new List<List<int>>();

        // 通过将行与列互换,填充转置矩阵
        for (int j = 0; j < cols; j++) {
            List<int> row = new List<int>();
            for (int i = 0; i < rows; i++) {

                // 赋值转置后的值
                row.Add(mat[i, j]);
            }
            tMat.Add(row);
        }

        return tMat; 
    }

    public static void Main()
    {
        int[,] mat = {
            {1, 1, 1, 1},
            {2, 2, 2, 2},
            {3, 3, 3, 3},
            {4, 4, 4, 4}
        };

        List<List<int>> res = transpose(mat);

        int rows = res.Count;
        int cols = res[0].Count;

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                Console.Write(res[i][j] + " ");
            }
            Console.WriteLine();
        }
    }
}

5. JavaScript

javascript 复制代码
function transpose(mat) {
  const rows = mat.length;           
  const cols = mat[0].length;      

  // 创建一个 cols 行 rows 列的结果矩阵,用于存储转置矩阵
  const tMat = new Array(cols).fill(0).map(() =>
    new Array(rows).fill(0));

  // 通过将行与列互换,填充转置矩阵
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {

      // 赋值转置后的值
      tMat[j][i] = mat[i][j];
    }
  }

  return tMat; 
}


// 测试代码
const mat = [[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3], [4, 4, 4, 4]];
const res = transpose(mat);
for (const row of res) {
  console.log(row.join(" "));
}

(三) 代码输出和算法复杂度

输出:

复制代码
1 2 3 4 
1 2 3 4 
1 2 3 4 
1 2 3 4 

时间复杂度: O(m*n)

空间复杂度:O(m*n)

三、【解法二】适用于方阵的常量空间解法 ------ 时间复杂度 O (m*n),空间复杂度 O (1)

(一) 解法思路

这种方法仅适用于方阵 (行数与列数相等的矩阵)。它被称为原地算法,因为无需使用任何额外空间即可完成矩阵转置。

实现步骤:

① 初始化两层嵌套循环:

  • 外层循环:i 从 0 到 n-1
  • 内层循环:j 从 i+1 到 n-1

这样可以避开对角线元素和已经交换过的位置。

② 交换元素:

  • 对每一对位置 (i, j),交换 mat[i][j]mat[j][i]
  • 这会让元素沿着主对角线对称互换

③ 持续交换,直到所有上三角区域的元素都与对应的下三角元素完成互换。

(二) 使用 5 种语言实现

1. C++

cpp 复制代码
#include <iostream>
#include <vector> 
using namespace std;

vector<vector<int>> transpose(vector<vector<int>>& mat) {
    int n = mat.size();  

    // 遍历矩阵的上三角部分
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {

            // 沿对角线交换元素
            swap(mat[i][j], mat[j][i]);
        }
    }

    return mat;  
}

int main() {

    vector<vector<int>> mat = {
    {1, 1, 1, 1},
    {2, 2, 2, 2},
    {3, 3, 3 ,3},
    {4, 4, 4, 4}
};

    vector<vector<int>> res = transpose(mat);

    for (const auto& row : res) {
        for (int elem : row) {
            cout << elem << " ";  
        }
        cout << endl; 
    }

    return 0;
}

2. Java

java 复制代码
import java.util.Arrays;

class DSA {

    public static int[][] transpose(int[][] mat) {
        int n = mat.length;

        // 遍历矩阵的上三角部分
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {

                // 沿对角线交换元素
                int temp = mat[i][j];
                mat[i][j] = mat[j][i];
                mat[j][i] = temp;
            }
        }

        return mat;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 1, 1, 1},
            {2, 2, 2, 2},
            {3, 3, 3, 3},
            {4, 4, 4, 4}
        };

        int[][] res = transpose(mat);

        for (int[] row : res) {
            for (int elem : row) {
                System.out.print(elem + " ");
            }
            System.out.println();
        }
    }
}

3. Python

python 复制代码
def transpose(mat):

    # 行数(因为是方阵,行和列数相等)
    n = len(mat)  

    # 遍历矩阵的上三角部分
    for i in range(n):
        for j in range(i + 1, n):

            # 沿对角线交换元素
            mat[i][j], mat[j][i] = mat[j][i], mat[i][j]

    return mat  


if __name__ == "__main__":
    mat = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
    res = transpose(mat)  
    for row in res:
        print(" ".join(map(str, row)))

4. C#

cs 复制代码
using System;
using System.Collections.Generic;

public class DSA {
    public static List<List<int>> transpose(int[,] mat) {

        // 行数和列数
        int rows = mat.GetLength(0);
        int cols = mat.GetLength(1);

        List<List<int>> result = new List<List<int>>();

        // 构建转置矩阵
        for (int j = 0; j < cols; j++) {
            List<int> row = new List<int>();
            for (int i = 0; i < rows; i++) {
                row.Add(mat[i, j]);
            }
            result.Add(row);
        }

        return result;  
    }

    public static void Main() {
        int[,] mat = {
            {1, 1, 1, 1},
            {2, 2, 2, 2},
            {3, 3, 3 ,3},
            {4, 4, 4, 4}
        };

        List<List<int>> res = transpose(mat);  

        int rows = res.Count;
        int cols = res[0].Count;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                Console.Write(res[i][j] + " ");
            }
            Console.WriteLine();
        }
    }
}

5. JavaScript

javascript 复制代码
function transpose(mat) {  
    
    // 行数(因为是方阵,行和列数相等)
    const n = mat.length;

    // 遍历矩阵的上三角部分
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            
            // 沿对角线交换元素
            let temp = mat[i][j];
            mat[i][j] = mat[j][i];
            mat[j][i] = temp;
        }
    }

    return mat;  
}

// 测试代码
const mat = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]];
const res = transpose(mat);  
for (const row of res) {
    console.log(row.join(" "));
}

(三) 代码输出和算法复杂度

输出:

复制代码
1 2 3 4 
1 2 3 4 
1 2 3 4 
1 2 3 4 

时间复杂度: O(m*n)

空间复杂度:O(1)

相关推荐
算法鑫探8 小时前
闰年判断:C语言实战解析
c语言·数据结构·算法·新人首发
WBluuue8 小时前
数据结构与算法:康托展开、约瑟夫环、完美洗牌
c++·算法
我叫黑大帅8 小时前
通过eino-ext如何正常indexer RAG?
后端·面试·go
木子墨5168 小时前
LeetCode 热题 100 精讲 | 并查集篇:最长连续序列 · 岛屿数量 · 省份数量 · 冗余连接 · 等式方程的可满足性
数据结构·c++·算法·leetcode
王老师青少年编程9 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌
c++·算法·编程·贪心·csp·信奥赛·均分纸牌
EQUINOX19 小时前
2026年码蹄杯 本科院校赛道&青少年挑战赛道提高组初赛(省赛)第一场,个人题解
算法
萝卜小白9 小时前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
Liangwei Lin10 小时前
洛谷 P3133 [USACO16JAN] Radio Contact G
数据结构·算法
weixin_5134499610 小时前
PCA、SVD 、 ICP 、kd-tree算法的简单整理总结
c++·人工智能·学习·算法·机器人