news 2026/7/21 6:42:16

Java 稀疏数组实现(二维数组 ↔ 稀疏数组 互转)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 稀疏数组实现(二维数组 ↔ 稀疏数组 互转)

原理说明

  1. 稀疏数组适用场景:二维数组中大量元素为默认值(0),只有少量有效数据,用稀疏数组压缩节省空间。
  2. 稀疏数组结构
    • 第一行:[总行数, 总列数, 有效元素个数]
    • 后续每一行:[行下标, 列下标, 对应数值]
  3. 转换流程
    • 二维数组 → 稀疏数组:遍历统计有效数据,构建稀疏数组
    • 稀疏数组 → 二维数组:读取首行列信息,新建空二维数组,回填有效值

完整代码

public class SparseArray { public static void main(String[] args) { // 1. 创建原始二维数组(模拟棋盘,0为空,1=黑子,2=白子) int[][] chessArr = new int[11][11]; chessArr[1][2] = 1; chessArr[2][3] = 2; chessArr[4][5] = 1; System.out.println("===== 原始二维数组 ====="); printTwoDArray(chessArr); // 2. 二维数组转稀疏数组 int[][] sparseArr = twoDToSparse(chessArr); System.out.println("\n===== 转换后的稀疏数组 ====="); printTwoDArray(sparseArr); // 3. 稀疏数组还原为二维数组 int[][] recoverArr = sparseToTwoD(sparseArr); System.out.println("\n===== 稀疏数组还原后的二维数组 ====="); printTwoDArray(recoverArr); } /** * 二维数组转稀疏数组 * @param twoDArr 原始二维数组 * @return 稀疏数组 */ public static int[][] twoDToSparse(int[][] twoDArr) { // 1. 统计有效数字总数(非0) int validCount = 0; int rowLen = twoDArr.length; int colLen = twoDArr[0].length; for (int i = 0; i < rowLen; i++) { for (int j = 0; j < colLen; j++) { if (twoDArr[i][j] != 0) { validCount++; } } } // 2. 创建稀疏数组:行数=有效数+1,固定3列(行、列、值) int[][] sparseArr = new int[validCount + 1][3]; // 第一行保存原数组信息:总行、总列、有效个数 sparseArr[0][0] = rowLen; sparseArr[0][1] = colLen; sparseArr[0][2] = validCount; // 3. 填充有效数据到稀疏数组 int index = 1; // 稀疏数组从第1行开始存数据 for (int i = 0; i < rowLen; i++) { for (int j = 0; j < colLen; j++) { if (twoDArr[i][j] != 0) { sparseArr[index][0] = i; sparseArr[index][1] = j; sparseArr[index][2] = twoDArr[i][j]; index++; } } } return sparseArr; } /** * 稀疏数组还原二维数组 * @param sparseArr 稀疏数组 * @return 还原后的原始二维数组 */ public static int[][] sparseToTwoD(int[][] sparseArr) { // 1. 读取稀疏数组第一行,获取原数组行列 int rowTotal = sparseArr[0][0]; int colTotal = sparseArr[0][1]; int[][] twoDArr = new int[rowTotal][colTotal]; // 2. 遍历稀疏数组剩余行,回填数值 for (int i = 1; i < sparseArr.length; i++) { int row = sparseArr[i][0]; int col = sparseArr[i][1]; int val = sparseArr[i][2]; twoDArr[row][col] = val; } return twoDArr; } /** * 工具方法:打印二维数组 */ public static void printTwoDArray(int[][] arr) { for (int[] row : arr) { for (int data : row) { System.out.printf("%d\t", data); } System.out.println(); } } }

运行输出结果

===== 原始二维数组 ===== 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ===== 转换后的稀疏数组 ===== 11 11 3 1 2 1 2 3 2 4 5 1 ===== 稀疏数组还原后的二维数组 ===== 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

核心方法拆解

  1. twoDToSparse
    • 两次循环:第一次统计非 0 元素数量,创建稀疏数组;第二次遍历赋值坐标与数值
  2. sparseToTwoD
    • 先用稀疏数组首行创建全 0 二维数组,再逐行读取坐标回填数据
  3. 工具方法printTwoDArray:统一打印逻辑,复用代码

拓展:持久化读写稀疏数组(存入文件 / 读取文件)

如果需要把稀疏数组保存到本地文件、下次读取恢复棋盘,可追加以下读写方法:

import java.io.*; // 稀疏数组写入文件 public static void writeSparseToFile(int[][] sparseArr, String path) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter(path)); for (int[] row : sparseArr) { bw.write(row[0] + "," + row[1] + "," + row[2]); bw.newLine(); } bw.close(); } // 文件读取还原稀疏数组 public static int[][] readSparseFromFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); String line; java.util.List<int[]> list = new java.util.ArrayList<>(); while ((line = br.readLine()) != null) { String[] split = line.split(","); int row = Integer.parseInt(split[0]); int col = Integer.parseInt(split[1]); int val = Integer.parseInt(split[2]); list.add(new int[]{row, col, val}); } br.close(); // list转二维数组 int[][] sparse = new int[list.size()][3]; for (int i = 0; i < list.size(); i++) { sparse[i] = list.get(i); } return sparse; }

调用示例:

writeSparseToFile(sparseArr, "chess.txt"); int[][] fileSparse = readSparseFromFile("chess.txt");
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 6:40:50

Java秋招突击:高频考点与实战策略精讲

如果你正在准备2025年或2026年的Java秋招&#xff0c;面对海量的八股文、复杂的场景题和层出不穷的新技术&#xff0c;感到无从下手、时间紧迫&#xff0c;那么这篇文章就是为你准备的。这不是一篇常规的“面经汇总”&#xff0c;而是一套经过验证的“邪修”突击策略——它不追…

作者头像 李华
网站建设 2026/7/21 6:40:24

吃透 Android 底层触控逻辑,根治项目常见交互 Bug

前言 做 Android 开发多年,绝大多数自定义控件、复杂页面交互异常,根源都指向触摸事件分发逻辑。很多开发者仅停留在 onTouch、onClick 表层调用,一旦遇到嵌套滚动、多层弹窗、多点触控、事件透传等复杂场景,只能靠临时重写方法强行兼容,无法从底层规避各类隐性 bug。 本…

作者头像 李华
网站建设 2026/7/21 6:40:18

C2000 ePWM数字比较子模块:硬件级实时保护与精准控制

1. 数字比较子模块&#xff1a;从信号到事件的精密转换 在电机驱动和开关电源这类对实时性要求极高的嵌入式系统中&#xff0c;硬件级的快速响应和精准控制是系统稳定运行的基石。想象一下&#xff0c;一个电机驱动器正在高速运转&#xff0c;突然发生了过流&#xff0c;如果这…

作者头像 李华
网站建设 2026/7/21 6:39:14

ARM 03 (i.MX6ULL 汇编点灯全流程)

开发板&#xff1a;IMX6ULL Mini配置启动文件汇编点亮LED一、启动流程cpu上电之后&#xff0c;pc指向0x00&#xff0c;指向异常向量表中的Reset指令&#xff0c;之后跳转到Reset指令对应的异常服务函数中。此时处于SVC模式&#xff0c;最终需要切换到system模式&#xff0c;所以…

作者头像 李华
网站建设 2026/7/21 6:38:58

小程序-Swiper 和 swiper-item 组件(轮播图)

让科技服务于人民 您的支持是我继续创作及维护的动力&#xff0c;感谢打赏&#xff0c;祝您工作顺利&#xff0c;生活美满&#xff01;&#xff01;&#xff01;wxml&#xff1a; <!--轮播图区域--> <!--indicator-dots 属性&#xff1a;显示面板指示点--> <swi…

作者头像 李华
网站建设 2026/7/21 6:38:03

C++水仙花数算法实现:从基础循环到函数封装与优化

1. 项目概述与核心价值 最近在带新人学习C基础语法时&#xff0c;发现很多朋友在掌握了循环和条件判断后&#xff0c;对于如何将这些知识整合起来解决一个具体问题&#xff0c;依然感到无从下手。一个经典的练手题目就是“水仙花数”&#xff0c;它看似简单&#xff0c;却完美…

作者头像 李华