1、螺旋打印矩阵
以下都要求:额外空间复杂度为O(1),即只用变量,原地打印
先确定左上点和右下点,先打出边框,然后向内调整点的位置,循环打印,如图所示:
完整代码如下
package cn.nupt;
/**
* @Description: 顺时针螺旋打印矩阵
*
* @author PizAn
* @date 2019年2月16日 下午10:01:39
*
*/
public class PrintMatrixSpiralOrder {
public void printMatrixSpiralOrder(int[][] arr) {
int tR = 0; // 左上角点的行号
int tC = 0; // 左上角点的列号
int dR = arr.length - 1; // 右下角点的行号:就是一维数组的数目 - 1
int dC = arr[0].length - 1; // 右下角点的列号:就是一维数组的长度
while (tR <= dR && tC <= dC) {
printLine(arr, tR++, tC++, dR--, dC--); // 打印以这四个点围成的边界,然后缩小圈子
}
}
private void printLine(int[][] arr, int tR, int tC, int dR, int dC) {
if (tR == dR) { // 行相同,即当还剩一列的时候,从上到下打印这一列(因为是顺时针旋转,必定是一圈打完之后调整四个点的位置)
/* for (int i = tC; i <= dC; i++) {
System.out.println(arr[tR][i] + " ");
}*/
while (tC <= dC) {
System.out.println(arr[tR][tC++]);
}
} else if (tC == dC) {// 列相同,即当还剩一行的时候,从左道由打印这一行(因为是顺时针旋转)
/* for (int i = tR; i <= dR; i++) {
System.out.println(arr[i][tC] + " ");
}*/
while (tR <= dR) {
System.out.println(arr[tR++][tC]);
}
}else { //打印边框
int curC = tC;
int curR = tR;
while (curC != dC) {
System.out.println(arr[tR][curC++] + " ");
}
while (curR != dR) {
System.out.println(arr[curR++][dC]+ " ");
}
while (curC != tC) {
System.out.println(arr[dR][curC--]+ " ");
}
while (curR != tR) {
System.out.println(arr[curR--][tC]+ " ");
}
}
}
}
2、90*旋转正方形矩阵
其实这个思路和上面的一样,从微观来操作,同样是从边框入手,依次交换90*边界上的几个点,然后缩小边界框,如下图所示
具体代码如下:
package cn.nupt;
/**
* @Description: 顺时针将矩阵旋转90*
*
* @author PizAn
* @date 2019年2月16日 下午10:02:40
*
*/
public class RotateMatrix {
public void rotateMatrix(int[][] arr) {
int tR = 0; // 左上角点的行号
int tC = 0; // 左上角点的列号
int dR = arr.length - 1; // 右下角点的行号:就是一维数组的数目 - 1
int dC = arr[0].length - 1; // 右下角点的列号:就是一维数组的长度
while (tR < dR) {
rotatePoint(arr, tR++, tC++, dR--, dC--);
}
}
//依次交换边界上的几个点
private void rotatePoint(int[][] arr, int tR, int tC, int dR, int dC) {
int times = dC - tC;
int temp = 0;
for (int i = 0; i < times; i++) {
temp = arr[tR][tC + i];
arr[tR][tC + i] = arr[dR - i][tC];
arr[dR - i][tC] = arr[dR][dC - i];
arr[dR][dC - i] = arr[tR + i][dC];
arr[tR + i][dC] = temp;
}
}
---------------------------------------------------
//打印数组
public void show(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[0].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
3、之字形打印矩阵
代码描述如下:
package cn.nupt;
import java.awt.dnd.DnDConstants;
/**
* @Description: "之"字形打印矩阵
*
* @author PizAn
* @date 2019年2月17日 下午2:23:39
*
*/
public class ZigZagPrintMatrix {
public static void printarrZigZag(int[][] arr) {
// 定义两个点A和B,各自的坐标初始化在左上角,
int aR = 0;
int aC = 0;
int bR = 0;
int bC = 0;
// 矩阵右下角的点的坐标
int enbR = arr.length - 1;
int enbC = arr[0].length - 1;
boolean flag = false;
// 我们开始移动左上角的两个点,这是边界的约束,即还没有到右下角的时候(注,A和B走的总路程是一样的)
while (aR != enbR + 1) {
// 打印A和B所在斜线上的点
printLevel(arr, aR, aC, bR, bC, flag);
// 调整A和B的位置,沿着边框走,遇到边界就拐弯,直到走到最下面的时候
aR = aC == enbC ? aR + 1 : aR;
aC = aC == enbC ? aC : aC + 1;
bC = bR == enbR ? bC + 1 : bC;
bR = bR == enbR ? bR : bR + 1;
// 为了能"之"字形打印,这里要将方向转一下,使用flag实现的
flag = !flag;
}
System.out.println();
}
// 打印A和B所在斜线上的点
public static void printLevel(int[][] m, int aR, int aC, int bR, int bC,
boolean f) {
if (f) {
while (aR != bR + 1) {
System.out.print(m[aR++][aC--] + " ");
}
} else {
while (bR != aR - 1) {
System.out.print(m[bR--][bC++] + " ");
}
}
}
/*
另一种写法
public void zigZagPrintMatrix(int[][] arr) {
int aR = 0; // 定义两个点A和B,各自的坐标初始化在左上角,
int aC = 0;
int bR = 0;
int bC = 0;
int dR = arr.length - 1; // 矩阵右下角的点的坐标
int dC = arr[0].length - 1;
boolean flag = true;
while (aC != dC + 1) { // 我们开始移动左上角的两个点,这是边界的约束,即还没有到右下角的时候(注,A和B走的总路程是一样的)
// 打印A和B所在斜线上的点
printLine(arr, aR, aC, bR, bC, flag);
// 调整A和B的位置,沿着边框走,遇到边界就拐弯,直到走到最下面的时候
bR = bC == dC ? bR + 1 : bR;
bC = bC == dC ? bC : bC + 1;
aR = aR == dR ? aR : aR + 1;
aC = aR == dR ? aC + 1 : aC;
// 为了能"之"字形打印,这里要将方向转一下,使用flag实现的
flag = !flag;
}
}
// 打印A和B所在斜线上的点
private void printLine(int[][] arr, int aR, int aC, int bR, int bC, boolean flag) {
if (flag) {
while (bR != aR + 1) {
System.out.println(arr[bR++][bC--]);
}
} else {
while (aR != bR - 1) {
System.out.println(arr[aR--][aC++]);
}
}
}
*/
}
4、在行列都排好序的矩阵中找数
时间复杂度为O(N+M),额外空间复杂度为O(1)
因为是行列都排好序的,所以要充分利用这个条件,如下图所示,从右上角的数开始:
- 如果偏大,那么下面的数就不用看了,向左移动
- 如果偏小,那么左边的数就不用看了,向下移动
- 这里注意一下边界
代码如下:
package cn.nupt;
/**
* @Description: 在行列都排好序的矩阵中找数
*
* @author PizAn
* @date 2019年2月17日 下午5:45:07
*
*/
public class FindNumInSortedMatrix {
public static boolean findNumInSortedMatrix(int[][] arr, int k) {
int row = 0;
int col = arr[0].length - 1;
while (row <= arr.length - 1 && col >= 0) { //边界条件
if (arr[row][col] == k) { //相等:直接返回
return true;
} else if (arr[row][col] > k) { //偏大:向左走
col--;
} else { //偏小,向下走
row++;
}
}
return false;
}
}