数组和矩阵结合的问题
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][top]);}
}
return list;
}
}
lt.59-螺旋矩阵 II
[案例需求]
[思路分析]
[代码实现]
lt.74-搜索二维矩阵
[案例需求]
[思路分析]
[代码实现]
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;
}
}