4. <tag-数组模拟矩阵>-lt.867 转置矩阵 + lt.54-螺旋矩阵 + lt.74-搜索二维矩阵 + 剑指Offer.29-顺时针打印矩阵 2.7
一, 数组和矩阵结合的问题
lt. 867 转置矩阵
[案例需求]
[思路分析]
- 没啥可说的, 无非就是新建二维数组, 遍历原来的二维数组, 把原二维数组的arr[行,列]放到新二维数组的arr_new[列,行]中去;
- 在实现过程中需要注意的一点: 在矩阵的转置过程中, 外层是遍历行, 内层是遍历列, 那么在内循环遍历列时, 我们遍历到哪里结束呢? 对角线处! j可以从0到i(下对角线), 也可以从 i到 arr.length-1(上对线);
[代码实现]
class Solution {
public int[][] transpose(int[][] matrix) {
//
int[][] res = new int[matrix[0].length][matrix.length];
for(int i = 0; i < matrix.length; i++){
for(int j = i; j < matrix[i].length; j++){
res[j][i] = matrix[i][j];
}
}
return res;
}
}
补充一点, 对于非方阵(行于列不相等的矩阵), 我们不能用上面这种对角线两边交换的方法解决, 而是老老实实的去遍历原先的矩阵, 仍然是 Resji = Matrix ij;
lt.54 螺旋矩阵
[案例需求]
[思路分析]
- 数组和矩阵一起结合考察(用数组模拟矩阵), 偏数学思想, 机器学习领域考察那是相当的多, 管咱屁事哈哈, 既然遇到了, 就把考察频度高的几道题甩出来
- 螺旋矩阵,即顺时针读取矩阵, 记录到结果集合中并返回,
- 我们最常用的解法就是, 记录矩阵的四个角, 不断的缩小角之间的范围, 直到目标数组中只剩下单纯的一列或一行数据, 甚至就剩一个数字, 同时也要记得把每次遍历的两个角之间的数, 添加到用于返回的集合中;
- 看上图最下面的提示, 矩阵是不为空的, 所以数组不会为空, 我们也不需要加什么特例条件了;
- 我们用left和right, 来记录每次左右遍历矩阵的左角和右角, 所以很显然, 从左向右遍历就是从left–>right遍历数组, 从右向左遍历就是从right–>left遍历数组;
- 我们用top和bottom,来记录每次上下遍历矩阵的上角和下角, 所以也很显然, 从上到下遍历就是从top–>bottom遍历数组, 从下到上遍历就是从bottom–>top遍历数组;
- 旋转跳跃我闭眼, 当我们左->右, 上->下, 右->左, 下->上遍历到矩阵只剩下一行或者一列,或者一个数字的时候, 再来一次顺序循环, 添加进集合, 就大功告成了
[代码实现]
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
//定义四个角
// top --> bottom 是从上往下遍历
// left --> right 是从左往右遍历
int top = 0; //top指明哪一行的行首
int bottom = matrix.length - 1; //bottom 指明哪一行的数目
int left = 0; //left指明哪一列的列首
int right = matrix[0].length - 1; //right指明哪一列
//特例(无,)因为题目给了: 1 <= matrix.length <= 10
//
//结果集合
List<Integer> list = new ArrayList<>();
while(top < bottom && left < right){
//从左到右遍历, 放入list
for(int i = left; i < right; i++){list.add(matrix[top][i]);} //当前top行的每一列
for(int i = top; i < bottom; i++){list.add(matrix[i][right]);} //当前right列的每一行
for(int i = right; i > left; i--){list.add(matrix[bottom][i]);} //当前bottom行的每一列
for(int i = bottom; i > top; i--){list.add(matrix[i][left]);} //当前left列的每一行
++left;
--right;
++top;
--bottom;
}
//边缘判断(当只剩下了一行. 或者一列, 或者一个数, 直接一次遍历加入集合即可)
//只剩下顺序一行
if(bottom == top){
for(int i = left; i <=right; i++){list.add(matrix[top][i]);}
}else if (left == right){
for(int i = top; i <= bottom; i++){list.add(matrix[i][left]);}
}
return list;
}
}
lt.74-搜索二维矩阵
[案例需求]
[思路分析]
- 本题主要是考察二分查找, 但我们先贴一个简单的写法: 倒序遍历;
- 因为给定的matrix矩阵是由左到右, 由上到下递增的, 所以我们理应能够想到从每行倒序往下遍历,
- 如果目标数>本行的最后一个数, 直接跳过本行;
- 如果目标数 < 本行的最后一个数, 就倒序往左遍历本行, 找到就直接返回, 发现有目标数> 当前数的, 直接跳出本行遍历, 继续下行的遍历
[代码实现]
解法一: 倒序遍历
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//解法一, 倒序遍历
//从矩阵的右端开始遍历:
//1. 遍历数 < 当前数, 跳到下一行进行遍历;
//2. 遍历数 > 当前述, 本行内往前进行遍历(倒序遍历)
//3. 遍历数 == 当前数, 直接return true;
//外层循环控制二维数组中的每个一维数组, 内层循环控制一维数组中的每个数
for(int i = 0; i < matrix.length; i++){
//二维数组中的每个数组的最后一个数的下标;
int last = matrix[i].length - 1;
for(int j = last; j >=0; j--){
if(target == matrix[i][j]) return true;
if(target > matrix[i][j]) continue;
}
}
return false;
}
}
解法二, 二分查找法:
[待补充]
剑指Offer.29-顺时针打印矩阵
[案例需求]
[思路分析]
- 解题思路跟 lt54. 螺旋矩阵完全相同, 只不过最后返回的是一个int类型的数组, 如果我们前面用的是list存储的话, 还需要把list数组转换为int类型的数组;
- 在这里要特别注意:
List<Integer> 是不能直接转换为 int[] 数组的, 使用 list.toAarry(int[]) 也不行!
—> 补充文章
[代码实现]
class Solution {
public int[] spiralOrder(int[][] matrix) {
//特例
if(matrix.length == 0 || matrix[0].length == 0) return new int[]{};
//记录四个角, 由左向右打印, 由上到下打印, 由右向做打印, 由下向上打印;
// left和right控制列, top和bottom控制行
int left = 0;
int right = matrix[0].length - 1;
int top = 0;
int bottom = matrix.length - 1;
//集合, 到最后会返回数组(集合->数组)
List<Integer> list = new ArrayList<>();
while(left < right && top < bottom){
for(int i = left; i < right; i++){list.add(matrix[top][i]);}
for(int i = top; i < bottom; i++){list.add(matrix[i][right]);}
for(int i = right; i > left; i--){list.add(matrix[bottom][i]);}
for(int i = bottom; i > top; i--){list.add(matrix[i][left]);}
++left;
--right;
++top;
--bottom;
}
//仅剩下一行了
if(bottom == top){
for(int i = left; i <= right; i++){
list.add(matrix[top][i]);
}//仅剩下一列了
}else if(left == right){
for(int i = top; i <=bottom; i++){
list.add(matrix[i][left]);
}
}
int[] arr = list.stream().mapToInt(Integer::valueOf).toArray();
return arr;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)