刷题使我快乐,满脸开心.jpg

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode.cn/problems/diagonal-traverse/
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

示例 1:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,4,7,5,3,6,8,9]

示例 2:

输入:mat = [[1,2],[3,4]]
输出:[1,2,3,4]

提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 104
  • 1 <= m * n <= 104
  • -105 <= mat[i][j] <= 105

思路

直接去模拟这个过程就好,注意边界的判断、不同情况下行为模式的变化就OK,没太多复杂的思路和机制~

直接上代码,细节在注释了

代码

func findDiagonalOrder(mat [][]int) []int {
	m, n, i, j := len(mat), len(mat[0]), 0, 0

	// 用一个方向表明是要斜向上扫描还是斜向下扫描
	// 斜向上那就扫到出界后,尝试往右移动一个,往右出界就往下移动一个
	// 斜向下那就扫到出界后,尝试往下移动一个,往下出界就往右移动一个
	direction := true
	var getNext func()
	getNext = func() {
		switch direction {
		case true:
			if j+1 >= n {
				i++
			} else {
				j++
			}
		case false:
			if i+1 >= m {
				j++
			} else {
				i++
			}
		}
		direction = !direction
	}

	res := make([]int, 0, m*n)
	// 这一层就是保证getNext()无论怎么移动一个都出界时候,说明就扫描完了
	for i < m && j < n && i >= 0 && j >= 0 {
		switch direction {
		case true:
			for i < m && j < n && i >= 0 && j >= 0 {
				res = append(res, mat[i][j])
				i--
				j++
			}
			// 回退。可以优化,但是优化后理解成本变高
			i++
			j--
		case false:
			for i < m && j < n && i >= 0 && j >= 0 {
				res = append(res, mat[i][j])
				i++
				j--
			}
			// 同回退
			i--
			j++
		}
		// 寻找下一个起始遍历点
		getNext()
	}
	return res
}