LeetCode54与59,一个口诀教会你旋转二维数组

362 阅读4分钟

Halo, 好久不见各位小伙伴,这几天工作是在是太忙了,忙到都没有足够的时间去继续写算法题目,那么今天一次性带来两道比较类似的题目,在LeetCode中属于中等难度的题目。但其实只要你掌握其中的要点,这一题其实跟简单的一样

那么今天带来的就是第54题,和59题。两题都涉及到旋转二维数组的概念。这两题分别是在说给定一个二维数组,按照螺旋的方式输出数字,以及按照螺旋的方式填充元素。其实都在描述的是同一个概念的东西

在LeetCode中同类型的题目,通常主要的中心思想不变只变其中参数偏多,这一题就把这个中心思想解释得淋漓尽致了。

我们要做旋转题目,我们必须要懂一个非常简单的概念,那么就是的四个方向,没错就是这简单的四个方向,如果你没有很明确的思路的话,你会走不下去的。

接下来,我们先看一下图 这个图中的二维数组很简单,但是要你螺旋输出他,也就是右->下->左->上的顺序不断的重复这个步骤,但是我们要十分注重边界,因为每一次循环其实是一个边界的移动。

比方说,我们第一回合从第一行开始输出1、2、3 结束这3个输出以后,我们必须把上边界 往下挪动一行,因为当下一次循环到此处时,必须是这一行下一行, 在这里没理解的小伙伴,我再举个例子从二维数组的右侧输出3、6、9此时的顺序是往下输出,但输出完后,右边界 必须往左挪动一行。

其实这个是有个口诀的右移上加下移右减左移下减上移左加 记住这4个口诀以后,再来参考我们的code,先来看题目54

func spiralOrder(matrix [][]int) []int {
 res := []int{}
 if len(matrix) == 0{
  return res
 }
 top := 0
 right := len(matrix[0])-1
 bottom := len(matrix) - 1
 left := 0
 direction := "right"

 for left<=right && top <= bottom{
  switch direction {
  case "right":
   for r:=left; r<=right; r++{
    res = append(res, matrix[top][r])
   }
   top ++ //做完后 整个跳到下一行
   direction = "bottom"
   break
  case "bottom":
   for b:= top; b<=bottom; b++{
    res = append(res, matrix[b][right])
   }
   right -- //做完后 整个右边往左靠一行
   direction = "left"
   break
  case "left":
   for l:= right; l>=left; l--{
    res = append(res, matrix[bottom][l])
   }
   bottom -- //做完后 整个下面往上一行
   direction = "top"
   break
  case "top":
   for t:= bottom; t>=top; t--{
    res = append(res, matrix[t][left])
   }
   left ++ //做完后 整个左边往右一行
   direction = "right"
   break
  }
 }
 return res
}

这里为什么left<=right 和 top<= bottom 就是因为刚才所说的边界问题,如果说这里不<=的话,那么每一次循环就有其中一行的数据,我们是获取不到的了。

有了这个基础以后,你再来看题目59, 就什么事情都迎面而解了。

func generateMatrix(n int) [][]int {
 res := make([][]int, n)
 if n == 1{
  tmp := []int{1}
  res[0] = tmp
  return res
 }
 if n > 1{
  for a := range res{
   res[a] = make([]int, n) //初始化二维数组
  }
 }
 top := 0
 right := n - 1
 bottom := n - 1
 left := 0
 direction := "right"

 count := 1
 for left <= right && top <= bottom {
  switch direction {
  case "right":
   for r := left; r <= right; r++ {
    res[top][r] = count
    count++
   }
   top++ //做完后 整个跳到下一行
   direction = "bottom"
   break
  case "bottom":
   for b := top; b <= bottom; b++ {
    res[b][right] = count
    count++
   }
   right-- //做完后 整个右边往左靠一行
   direction = "left"
   break
  case "left":
   for l := right; l >= left; l-- {
    res[bottom][l] = count
    count++
   }
   bottom -- //做完后 整个下面往上一行
   direction = "top"
   break
  case "top":
   for t:= bottom; t>=top; t--{
    res[t][left] = count
    count++
   }
   left ++ //做完后 整个左边往右一行
   direction = "right"
   break
  }
 }
 return res
}

第59题目,就是初始化一个二维数组为n的长度然后往里面添加一个count然后,就没然后了,这两题非常简单。我会把我做的所有题目的代码都放在Github上哦,希望小伙伴们可以去点个star

Github代码合集(持续更新...)

其他相关解题思路

一篇文章带你了解【图】的结构及相关【算法】

LeetCode 31 - 下一个排序 - 解题思路记录 - Golang

LeetCode 18 - 4数之和 - 解题思路记录 - Golang

LeetCode 55 - 跳跃游戏 - 解题思路记录(动态规划优化版) - GoLang

LeetCode 55 - 跳跃游戏 - 解题思路记录(递归+动态规划法) - Golang

LeetCode 53 - 最大子序和 - 解题思路记录(附带动态规划) - GoLang

LeetCode 49 - 字母异位词分组 - 解题思路记录 - Golang

LeetCode 21 - 合并有序链表 - 解题思路记录 - GoLang

LeetCode 2 - 两数之和 - 解题思路记录 - GoLang

LeetCode 12 - 罗马数字 - 解题思路记录 - GoLang

LeetCode 15 - 3数之和 - 解题思路记录 - GoLang

LeetCode 5 - 回文串 - 解题思路记录 - GoLang