剑指offer 19. 顺时针打印矩阵 & leetcode 剑指 Offer 29. 顺时针打印矩阵 & 螺旋矩阵 (Java/Golang)

19. 顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路:

链接:https://www.nowcoder.com/questionTerminal/9b4c81a02cd34f76be2659fa0d54342a?answerType=1&f=discussion

定义四个变量代表范围,up、down、left、right

1. 向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 up 加一,同时判断是否和代表下边界的 down 交错

2. 向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错

3. 向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 down 减一,同时判断是否和代表上边界的 up 交错

4. 向上走存入整列的值,当存入后,该列再也不会被遍历,代表左边界的 left 加一,同时判断是否和代表右边界的 right 交错

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> printMatrix(int [][] matrix) {
 4        // 判断矩阵是否为空
 5         ArrayList<Integer> list = new ArrayList<>();
 6         int up = 0, down = matrix.length - 1;
 7         int left = 0, right = matrix[0].length - 1;
 8         if(matrix == null || down < 0 || left < 0){
 9             return list;
10         }
11         
12         // 四个方向遍历矩阵, 动态更新四个边界值
13         int col, row;
14         while(true){
15             // 最上面这行向右
16             for(col = left; col <= right; col++){
17                  list.add(matrix[up][col]);
18             }
19             up++;        // 更新上边界
20             if(down < up){
21                 break;
22             }
23             // 最右边这行向下
24             for(row = up; row <= down; row++){
25                 list.add(matrix[row][right]);
26             }
27             right--;    // 更新右边界
28             if(left > right){
29                 break;        // 如果越界则跳出循环
30             }
31             // 最下面这行向左
32             for(col = right; col >= left; col--){
33                 list.add(matrix[down][col]);
34             }
35             down--;    // 更新下边界
36             if(up > down){
37                 break;        // 如果越界则跳出循环
38             }
39             // 最左边这行向上
40             for(row = down; row >= up; row--){
41                 list.add(matrix[row][left]);
42             }
43             left++;    // 更新左边界
44             if(left > right){
45                 break;
46             }
47         }
48         return list;
49     }
50 }

leetcode运行时间为1ms - 96.82%, 空间为40.2MB - 37.45%

复杂度分析:

时间复杂度:遍历了整个矩阵,所以时间复杂度为O(rows*cols)

空间复杂度:除了存储结果的矩阵,其他的空间都是常量级的,所以空间复杂度为O(1)

Golang 写法

毕业后面试第一题算法题,今天面试被问到了这题,但是太久了没刷题了,而且对 golang 的二维数组遍历和长度获取不是很熟,导致捣鼓了很久也没写完,难过想哭😭😭😭

package main

import "fmt"

// 输出螺旋矩阵
func printMatrix(arr [][]int)  {
	if arr == nil || len(arr) == 0 {
		return
	}

	// 左右边界和上下边界
	leftBorder, rightBorder := 0, len(arr[0]) - 1
	upBorder, downBorder := 0, len(arr) - 1
	var i, j int

	for ; ; {
		// 从左往右遍历最上面那行
		for j = leftBorder; j <= rightBorder; j++ {
			fmt.Printf("%v ", arr[upBorder][j])
		}
		upBorder++ // 更新上边界
		if upBorder > downBorder { // // 上边界超过下边界,越界直接结束循环
			break
		}

		// 从上往下遍历最右边那行
		for i = upBorder; i <= downBorder; i++ {
			fmt.Printf("%v ", arr[i][rightBorder])
		}
		rightBorder-- // 更新右边界
		if rightBorder < leftBorder { // // 右边界小于左边界,越界直接结束循环
			break
		}

		// 从右往左遍历最下面那行
		for j = rightBorder; j >= leftBorder; j-- {
			fmt.Printf("%v ", arr[downBorder][j])
		}
		downBorder-- // 更新下边界
		if downBorder < upBorder { // // 下边界小于上边界了,越界直接结束循环
			break
		}

		// 从下往上遍历最左边那行
		for i = downBorder; i >= upBorder; i-- {
			fmt.Printf("%v ", arr[i][leftBorder])
		}
		leftBorder++ // 更新左边界
		if leftBorder > rightBorder { // 左边界大于右边界,越界直接结束循环
			break
		}
	}
	fmt.Printf("\n")
}

 测试 case 4个:正常二维数组,单行,单列,空数组

func main()  {

	arr := [][]int{
		{1, 2, 3, 4, 5},
		{14, 15, 16, 17, 6},
		{13, 20, 19, 18, 7},
		{12, 11, 10, 9, 8},
	}
	printMatrix(arr) // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
	arr = [][]int{
		{1, 2, 3, 4, 5},
	}
	printMatrix(arr) // 1 2 3 4 5
	arr = [][]int {
		{1}, {2}, {3}, {4}, {5},
	}
	printMatrix(arr) // 1 2 3 4 5
	arr = [][]int {

	}
	printMatrix(arr) //
}
posted @ 2020-03-26 21:48  Lucky小黄人^_^  阅读(173)  评论(0)    收藏  举报