前言
记录刷 LeetCode 时遇到的模拟相关题目
59.螺旋矩阵 II
这道题通过循环从外到里处理矩阵的一行一列,共有四个循环,形式上都是一样的,边界条件很多,这时我们就要注意 循环中遵循“不变量” 的原则,每一次行的遍历都要按照一定的规则来遍历
public int[][] generateMatrix(int n) {
if(n == 1){
return new int[][]{{1}};
}
int[][] matrix = new int[n][n];
int time = n - 1;
int row = 0;
int column = 0;
int num = 1; //用num表示每次要填入的数字
int end = n * n + 1;
while (num != end){
//这里四个循环代表了矩形的四条边,每一条边都采用左闭右开的方式
//进行遍历,所以每一次循环都要执行n-1次,用i来作为计数器
//num最大只能到 n*n,由于使用的是num++,所以当num到达n*n+1时,矩阵中所有数字均已填入
for(int i = 1;i <= time && num != end;i++){
matrix[row][column++] = num++;
}
for(int i = 1;i <= time && num != end;i++){
matrix[row++][column] = num++;
}
for(int i = 1;i <= time && num != end;i++){
matrix[row][column--] = num++;
}
for(int i = 1;i <= time && num != end;i++){
matrix[row--][column] = num++;
}
//最左边赋值完后要让指针回到下一个最顶边进行新一轮的赋值
row++;
column++;
//如果本次循环中每一条边都赋值两个元素,说明下一次循环只剩最后一个中心点需要赋值,此时time不能减2而应该是等于1
time = time == 2 ? 1 : time - 2;
}
return matrix;
}
54.螺旋矩阵
上面的 59 题会做,这道题思路基本上是一样的
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
//处理矩阵只有一行的特例
if(matrix.length == 1){
for (int i = 0; i < matrix[0].length; i++) {
result.add(matrix[0][i]);
}
return result;
}
int rowLength = matrix.length;
int columnLength = matrix[0].length;
//row跟column记录当前访问的元素
int row = 0;
int column = 0;
//numCount表示一共需要访问多少个元素
int numCount = (rowLength) * (columnLength);
//count记录当前已经访问过了多少个元素
int count = 0;
//循环条件是档期按已经访问过的元素个数小于一共需要访问的个数
while (count < numCount){
//这个if分支是应对遍历到最后只剩最后一个元素(矩阵正中间)时的情况
//对于[[1,2,3],[4,5,6],[7,8,9]]这个样例,如果没有这个if分支,按照1->2->3->6->9->8->7->4的顺序执行完一个最外层的while后,此时rowLength跟columnLength都为1,再次进入while后会死循环
if(currentCount + 1 == numCount){
result.add(matrix[row][column]);
count++;
}
//采取左闭右开的访问规则,即每一行/列的最后一个元素留到作为下一个列/行的第一个元素再访问
for(int i = 1;i <= columnLength - 1 && count < numCount;i++){
result.add(matrix[row][column++]);
count++;
}
for(int i = 1;i <= rowLength - 1 && count < numCount;i++){
result.add(matrix[row++][column]);
count++;
}
for(int i = 1;i <= columnLength - 1 && count < numCount;i++){
result.add(matrix[row][column--]);
count++;
}
for(int i = 1;i <= rowLength - 1 && count < numCount;i++){
result.add(matrix[row--][column]);
count++;
}
row++;
column++;
rowLength -= 2;
columnLength -= 2;
}
return result;
}
867. 转置矩阵
根据矩阵转置的定义,利用 res[j][i] = matrix[i][j] 进行模拟转置即可
public int[][] transpose(int[][] matrix) {
introw = matrix.length;
int column = matrix[0].length;
int[][] res = new int[column][row];
for(int i = 0;i < row;i++){
for(int j = 0;j < column;j++){
res[j][i] = matrix[i][j];
}
}
return res;
}
66. 加一
从低位往高位按位模拟加法即可,要注意的是可能会产生进位
- 根据题意,首位是 0 的话 digits 表示的就是 0,直接返回 1
- 如果最低位小于 9,那就直接加一然后返回,如 [1,8,8],直接返回 [1,8,9]
- 如果最低位等于 9,那就加一进位,进位后可以被进的高一位也要进位,所以要一直进位到出现进位完小于等于 9 的位,
- 或者一直进位到最高位然后最左边补个 1,如 [1,9,9],进位进到 1,得到 [2,0,0];又如 [9,9,9],进位完最左边要多补一位,得到 [1,0,0,0]
public int[] plusOne(int[] digits) {
if(digits[0] == 0) return new int[]{1};
int len = digits.length;
if(digits[len - 1] < 9){
digits[len - 1] += 1;
return digits;
}
int index = len - 1;
digits[index] = 10;
while(digits[index] > 9){
digits[index--] = 0;
//已经进到最高位了,所以多补一个最高位的1
if(index == -1){
int[] ans = new int[len + 1];
ans[0] = 1;
System.arraycopy(digits,0,ans,1,len);
return ans;
}
digits[index] += 1;
}
return digits;
}
498. 对角线遍历
根据示意图可以看出,对角线遍历的路径为,从 [0,0] 开始,先沿从左下角到右上角的方向遍历,当遍历到边界时,遍历下一条对角线,然后沿从右上角到左下角的方向遍历,当遍历到边界时,继续换到下一条对角线,遍历方向改为从左下角到右上角,以此类推
指针 i,j 指向当前遍历的元素横纵坐标,flag 变量标记当前的遍历方向,为 true 时从左下角到右上角,否则相反
那么当 flag 为 true 时,i,j 的变化应该是 i--,j++,当然在变化前要判断变化后的值是否还在矩阵范围内。如果变化后会超出范围,就不能变化,而且说明要遍历下一条对角线了。由于遍历起点为 [0,0],所以为了遍历下一条对角线,j 需要尝试加一指向同一行下一列的那个元素,如果 j + 1 不在矩阵范围,说明已经遍历到了最长的那条对角线,为了遍历下一条对角线,此时需要指向同一列的下一行的那个元素,即 i++。另外一个方向上的操作同理,不再赘述:
public int[] findDiagonalOrder(int[][] mat) {
boolean flag = true;
int i = 0,j = 0,m = mat.length,n = mat[0].length,index = 0,count = m * n;
int[] res = new int[count];
while(index < count){
res[index++] = mat[i][j];
if(flag){ //从左下角到右上角的方向
if(i - 1 >= 0 && j + 1 < n){
i--;
j++;
}else{
flag = false;
if(j + 1 >= n) i++;
else j++;
}
}else{ //从右上角到左下角的方向
if(i + 1 < m && j - 1 >= 0){
i++;
j--;
}else{
flag = true;
if(i + 1 >= m) j++;
else i++;
}
}
}
return res;
}