当前位置: 首页 > news >正文

二维数组“降维”到一维数组----从零开始的算法

一.核心:

前提:核心前提:元素总数不变,且操作基于“行优先遍历”顺序(这里的行优先,对象指的是二维数组)。

• 适用场景:

当题目要求将一个矩阵按特定顺序重新排列为新的行、列维度,且元素顺序在内存中的线性排列保持一致时,就可以使用一维下标作为中间桥梁。适用场景包括:

  • 矩阵变形(如 LeetCode 566):将m×n矩阵转为r×c矩阵。

  • 图像处理:将 RGB 图像的 3 维数组展平为一维向量输入神经网络(Flatten 层)。

  • 数据扁平化:将二维表格数据按行拼接成一维数组用于存储或传输。

  • 矩阵运算底层优化:在实现矩阵乘法、卷积等操作时,将矩阵按行主序或列主序线性化,利用 CPU 缓存局部性加速计算。

条件:你只需要按线性下标顺序逐个搬运元素,而不涉及复杂的旋转、转置或条件筛选。因为线性下标与二维坐标的映射是双射(一一对应),所以只要总数相同,任意合法维度都可重塑。

二.行主序 or 列主序

顾名思义

  • 行主序(Row-major order):在内存中,同一行的元素连续存放,行与行之间顺序排列。
    即:第一行的所有元素 → 第二行的所有元素 → … → 最后一行的所有元素。

  • 列主序(Column-major order):在内存中,同一列的元素连续存放,列与列之间顺序排列。
    即:第一列的所有元素 → 第二列的所有元素 → … → 最后一列的所有元素。

例子;

示例(矩阵[[1,2,3],[4,5,6]]
存储顺序内存中的线性排列(下标从0开始)
行主序[1, 2, 3, 4, 5, 6]
列主序[1, 4, 2, 5, 3, 6]

• 坐标映射:

坐标映射公式(设矩阵列数为C,总列数固定)
存储顺序二维坐标(row, col)→ 一维下标index一维下标index→ 二维坐标(row, col)
行主序index = row * C + colrow = index / C
col = index % C
列主序index = col * R + row(R为行数)row = index % R
col = index / R

补充:

性能影响:局部性原理

  • 行主序访问行元素:连续内存,缓存命中率高,速度极快。

  • 行主序访问列元素:内存跳跃,缓存频繁失效,速度慢(可能慢几十倍)

例题:

leetcode 566 重塑数组

在 MATLAB 中,有一个非常有用的函数reshape,它可以将一个m x n矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。

给你一个由二维数组mat表示的m x n矩阵,以及两个正整数rc,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:

输入:mat = [[1,2],[3,4]], r = 1, c = 4输出:[[1,2,3,4]]

示例 2:

输入:mat = [[1,2],[3,4]], r = 2, c = 4输出:[[1,2],[3,4]]
#include<iostream> #include<vector> using namespace std; class Solution { public: vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) { int m = mat.size(); int n = mat[0].size(); if (m*n != r*c) return mat; vector<vector<int>> answer(r,vector<int>(c,0)); for (int i = 0; i < m; i++){ for (int j = 0; j < n; j++){ int newrow = 0,newcol = 0; int temp = i*n + j; newrow = temp / c; newcol = temp % c; answer[newrow][newcol] = mat[i][j]; } } return answer; } };

或者也可以

#include<iostream> #include<vector> using namespace std; class Solution { public: vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) { int m = mat.size(); int n = mat[0].size(); if (m * n != r *c) { return mat; } vector<vector<int>> answer(r,vector<int>(c)); for (int i = 0; i < m*n ; i++){ int newRow = i / c; //第i行 int newcol = i % c; // 第j个 新的 int oldRow = i / n; int oldcol = i % n; answer[newRow][newcol] = mat[oldRow][oldcol]; } return answer; } };

两者的时间复杂度和空间复杂度都是一样的

前者更加接近于模拟的方式,便于理解。

本章是学习哈希表做题的时候,发现的问题,特此单开一章用于总结。

希望正在阅读的你有所帮助。

喜欢我的话可以点点免费的赞和关注,谢谢支持!

http://www.jsqmd.com/news/656289/

相关文章:

  • 【资源管理】信息系统项目管理师论文范文
  • BepInEx终极指南:3分钟学会Unity游戏插件框架,让游戏扩展如此简单![特殊字符]
  • 避开伽马能谱分析的5个常见坑:从探测器选择到数据解读的实战经验
  • Kandinsky-5.0-I2V-Lite-5s Web服务安全加固:JWT鉴权+速率限制+上传文件类型校验
  • 宝武集团复购无人矿卡,易控智驾从“煤矿龙头“迈向“全矿种“解决方案提供商
  • 告别数据线!用ESP32蓝牙串口和手机App轻松互传数据(保姆级教程)
  • vue2+vue3 知识点讲解
  • 【数据库】undo log 和 redo log 区别
  • 5大核心优势解析:Open WebUI如何重塑企业级AI应用开发体验
  • 直驱赋能,精贴未来——雅科贝思XYZ模组助力半导体高速固晶设备升级
  • YAH2460型圆振动筛:从设计原理到工业实践的可靠性革新
  • 别再只会用printenv了!U-Boot环境变量实战:用setenv/saveenv定制你的i.MX6ULL启动流程
  • 避开ESP32看门狗的坑:从Ticker定时器触发重启,到理解IDLE任务与CPU核心分配
  • 【智能代码生成安全红线】:20年资深架构师亲授5大高危漏洞自动拦截法则
  • CronJob为什么需要设置concurrencyPolicy: Forbid
  • 从Matlab到Lumerical脚本:手把手教你迁移仿真思维,快速上手FDTD自动化
  • 手绘风格白板Excalidraw:3分钟快速上手终极指南
  • YOLO 系列:YOLO-World 零样本检测2026微调实战:无需重新训练即可识别全新类别
  • 《Vue3 入门核心名词解释》
  • 告别显示器!用笔记本和一根网线玩转树莓派4B:SSH+VNC远程桌面完整配置流程
  • R:pheatmap实战指南 | 从数据导入到高级注释热图的完整绘制与调参解析
  • 从零上手带外管理:IPMITOOL核心功能实战指南
  • CentOS 8.1上Ceph Octopus集群保姆级搭建:从Docker配置到CephFS挂载全流程
  • 十九、观察者模式
  • 保姆级教程:在Ubuntu 22.04上从零部署Picovoice离线语音助手(含树莓派兼容指南)
  • Comsol新手必看:5步搞定CPU水冷散热系统仿真(附模型文件下载)
  • R语言实战:用microeco和meconetcomp包5分钟搞定微生物网络稳定性分析(附完整代码)
  • 不只是降噪:聊聊声加ENC算法在TWS耳机通话中的AEC与ANC联动
  • Arduino ESP32终极开发指南:从零开始打造物联网项目
  • 如果 Seedance 3.0 真把长视频 + 多语言口型同步 + 低成本做起来,广告和短剧团队可能会先挨刀