【leet-code清晰解题思路💯✅】6. Z 字形变换

89 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,[点击查看活动详情](juejin.cn/post/714765…

题目描述

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"

示例 2:

输入: s = "PAYPALISHIRING", numRows = 4
输出: "PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

输入: s = "A", numRows = 1
输出: "A"

提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、',' 和 '.' 组成
  • 1 <= numRows <= 1000

解题思路

  • 在一个z字形位置游走,最直接的是开一个二维数组,根据规则在对应位置填数,然后再正常的从左向右从上向下进行输出。因为开了二维数组,维度约为nrows*len(s)/2,化简在一些情况下为O(n^2)的空间和时间复杂度,捉襟见肘。
func convert(s string, numRows int) string {
   if len(s) == 1 || numRows == 1 {
      return s
   }
   strs := []byte(s)
   w := len(s)/2 + 1
   m := make([][]byte, numRows)
   for i := 0; i < len(m); i++ {
      m[i] = make([]byte, w)
   }
   i := 0
   x, y := 0, 0
   for i < len(s) {
      for x < numRows-1 && i < len(s) {
         m[x][y] = strs[i]
         i++
         x++
      }
      for x > 0 && y < w && i < len(strs) {
         m[x][y] = strs[i]
         x--
         y++
         i++
      }
   }
   ans := make([]byte, 0, len(s))
   for _, bytes := range m {
      for _, b := range bytes {
         if b != 0 {
            ans = append(ans, b)
         }
      }
   }

   return string(ans)
}

image.png

  • 下面我们尝试找到字母顺序的数学规律,直接按规律输出即可。列表: image.png
  • 可以看到每一竖列,初值为行号,公差为2n-2;斜着的初值2n-2-行号,公差也是2n-2。这样子可以直接输出结果了。这样空间,时间复杂度都降为O(n),不错不错。
func convert2(s string, numRows int) string {
   if len(s) == 1 || numRows == 1 {
      return s
   }
   strs := []byte(s)
   m := make([]byte, 0, len(strs))
   for i := 0; i < numRows; i++ {

      for k := 0; i+k*(2*numRows-2) < len(strs); k++ {
         m = append(m, strs[i+k*(2*numRows-2)])
         if i == 0 || i == numRows-1 {
            continue
         }
         if 2*numRows-2-i+k*(2*numRows-2) < len(strs) {
            m = append(m, strs[2*numRows-2-i+k*(2*numRows-2)])
         }

      }

   }
   return string(m)
}

image.png