旋转矩阵
题目
不使用额外空间,将二维矩阵顺时针旋转90度
链接
思路
先将矩阵中的元素左右交换,再沿着对角线交换
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
if (len == 1) {
return;
}
for (int i = 0; i < len; i++) {
for (int j = 0; j < len / 2; j++) {
swap(matrix, i, j, i, len - j - 1);
}
}
for (int i = 0; i < len; i++) {
for (int j = 0; j < len - i; j++) {
swap(matrix, i, j, len - j - 1, len - i -1);
}
}
}
// 交换矩阵中的两个元素
private void swap(int[][] matrix, int x1, int y1, int x2, int y2) {
int tmp = matrix[x1][y1];
matrix[x1][y1] = matrix[x2][y2];
matrix[x2][y2] = tmp;
}
}
螺旋矩阵(顺时针打印矩阵)
题目
顺时针获取矩阵中的元素,返回一个list
链接
思路
定义上下左右四个分割线,当走完一行或者一列对应的分割线就移动,当两个分割线相撞时就表示遍历结束了
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
// 定义上、左、右、下四条分割线
int below = 0, left = 0, right = cols - 1, bottom = rows - 1;
List<Integer> list = new ArrayList<>();
while (true) {
// 从左到右遍历
for (int i = left; i <= right; i++) {
list.add(matrix[below][i]);
}
if (below++ == bottom) {
break;
}
// 从上到下遍历
for (int i = below; i <= bottom; i++) {
list.add(matrix[i][right]);
}
if (right-- == left) {
break;
}
// 从右到左遍历
for (int i = right; i >= left; i--) {
list.add(matrix[bottom][i]);
}
if (bottom-- == below) {
break;
}
// 从下到上遍历
for (int i = bottom; i >= below; i--) {
list.add(matrix[i][left]);
}
if (left++ == right) {
break;
}
}
return list;
}
}
矩阵中的路径
题目
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
思路
深度优先遍历,对矩阵中的每个元素上下左右四个方向依次尝试
class Solution {
public boolean exist(char[][] board, String word) {
char[] words = word.toCharArray();
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (dfs(board, words, i, j, 0)) {
return true;
}
}
}
return false;
}
// k记录成功匹配的字母个数
private boolean dfs(char[][] board, char[] words, int i, int j, int k) {
// 数组越界或当前字符不在目标字符串内,直接返回false
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != words[k]) {
return false;
}
if (words.length == k + 1) {
return true;
}
// 更改值表示当前位置已访问过
board[i][j] = '\0';
boolean res = dfs(board, words, i + 1, j, k + 1) || dfs(board, words, i - 1, j, k + 1) || dfs(board, words, i, j + 1, k + 1) || dfs(board, words, i, j - 1, k + 1);
// 恢复为初始值
board[i][j] = words[k];
return res;
}
}
搜索二维矩阵
题目
判断二维矩阵中是否存在目标值,该矩阵每行递增,每列递增
链接
思路
每次将矩阵右上角的值与目标值比较,若该值大于目标值,表示目标值在该行中;若该值小于目标值,则排除当前行,重复操作直至找到目标值
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row = matrix.length;
int col = matrix[0].length;
int r = 0, c = col - 1;
while (r < row && c >= 0) {
if (matrix[r][c] == target) {
return true;
} else if (matrix[r][c] > target) {
c--;
} else {
r++;
}
}
return false;
}
}
矩阵置零
题目
给定一个二维矩阵,若某元素为0,则对应的行和列的全部元素都要改为0,请原地修改矩阵
链接
思路
遍历矩阵除第一行第一列以外的所有元素,若某元素为0,则将其对应的第一行和第一列位置的值改为0,相当于一个标记,表示对应的行和列后续都要改为0;但第一行和第一列可能原本就存在0,会和标记冲突,因此要先遍历第一行和第一列,用两个布尔型变量记录第一行和第一列是否要置零
class Solution {
public void setZeroes(int[][] matrix) {
// 记录第一行和第一列是否要置为0
boolean rowZero = false;
boolean colZero = false;
int i = 0, j = 0;
for (i = 0; i < matrix[0].length; i++) {
if (matrix[0][i] == 0) {
rowZero = true;
break;
}
}
for (j = 0; j < matrix.length; j++) {
if (matrix[j][0] == 0) {
colZero = true;
break;
}
}
for (i = 1; i < matrix.length; i++) {
for (j = 1; j < matrix[0].length; j++) {
// 若某元素为0,将第一行和第一列的对应位置置为0,相当于标记
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (i = 1; i < matrix.length; i++) {
for (j = 1; j < matrix[0].length; j++) {
// 根据标记对相应的行和列置零
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 根据布尔变量决定第一行和第一列是否置零
if (rowZero) {
for (i = 0; i < matrix[0].length; i++) {
matrix[0][i] = 0;
}
}
if (colZero) {
for (j = 0; j < matrix.length; j++) {
matrix[j][0] = 0;
}
}
}
}