每日算法之ZigZag 转换问题

The ZigZag Conversion Problem ZigZag 转换问题

(leetcode.com/problems/zi...).

今天的算法是 ZigZag 转换问题。给你一个字符串和一些行。这个想法是,给定的字符串以锯齿形模式写入,并且该函数应该返回该字符串在逐行读取时的读取结果。

我认为这个问题的写法特别令人困惑,所以让我们看一个例子。

如果给定的字符串是"ALGORITHMOFTHEDAY",并且行数是 4,则它看起来像这样:

css 复制代码
A      T      H
L   I  H   T  E
G  R   M  F   D  Y
O      O      A

逐行读取,您会得到字符串"ATHLIHTEGRMFDYOOA",这将是该函数的输出。

我认为这是一种分解示例可以帮助您找到解决方案的算法。因此,我将首先通过一个示例并考虑如何解决该问题,然后我将讨论代码。

解决锯齿形调整浪问题

假设给定字符串"ABCDEFGH",锯齿形的行数为 3。写下来,看起来像这样:

去掉所有字母,我们有三行,可以将其视为三个数组。

现在,为了构建这个锯齿形单词,我们可以在给定的字符串中逐个字母。从前三个字母"ABC"开始,我们可以将它们放在三行(或数组)的开头。一旦我们到达底行,我们就知道我们无法在该方向添加更多字母,因此我们必须开始反转方向。

我们将在这个相反的方向上添加"D"和"E",但是一旦我们到达第一行,我们再次知道我们不能继续这个方向。

我们可以继续做同样的事情,沿一个方向添加字母,直到到达最后一行,然后反转方向,直到添加了字符串的所有字母。

去掉数组的行(本质上是将这些数组转换为字符串),我们得到三个字符串。

将它们逐行相加,我们得到结果:"AEBDFHCG"。

这个例子展示了我将如何解决这个问题:为给定的行构建相同数量的数组,将给定字符串的字母添加到每个数组,直到到达最后一个数组,然后反转方向。一旦我们到达第一个数组,再次反转方向。继续这样做,直到我们用完输入字符串中的字母为止。最后,将各个数组的字母连接起来形成字符串,然后将这些字符串连接起来形成一个最终字符串。

Coding the ZigZag Problem 编写 ZigZag 问题的代码

现在我们已经完成了一个示例,我们可以继续编写解决方案。在该问题中,我们给出了字符串 s 和一些行 numRows 。要做的第一件事是考虑基本情况:如果只有一行,那么甚至不可能出现锯齿形,因此我们可以返回字符串。另一种基本情况是,如果字符串比给定的行数短,在这种情况下,锯齿形也不可能出现,因此我们可以再次返回字符串。

javascript 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  //...
}

现在我们需要构建一些变量。首先是一个存储其他数组 rows 的数组。 rows 中的每个数组将存储一行之字形图案。我们还需要为当前所在行构建一个计数器 currentRow ,该计数器从 0 开始。我们需要一个等于布尔值的变量,该变量表示我们是否正在切换方向 < b3>。最后,我们需要创建一个最后返回的空字符串 result

ini 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  let rows = [];
  let currentRow = 0;
  let reverse = false;
  let result = "";

  //...
}

我们现在想要构建 numRows 中给出的行数。为此,我们可以创建一个 for 循环,从 0 到 numRows ,并每次构建一个新的空白数组。

ini 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  let rows = [];
  let currentRow = 0;
  let reverse = false;
  let result = "";

  for (let i = 0; i < numRows; i++) {
    rows[i] = [];
  }

  //...
}

现在,我们要遍历"s"中的每个字符,并将其推送到不同的行,直到完成每个字母。因此,这是使用 for 循环的好地方,从第一个字母(在索引 0 处)开始,直到最后一个字母(在 s.length 处)。

在 for 循环内,我们希望将此字母 ( s[i] ) 推送到基于 currentRow 的行。如果我们向下走, currentRow 就会变大;如果我们反转方向, currentRow 就会变小------所以我们应该在这里有一个条件语句。如果 reverse 为 true,则 currentRow 应该变小;否则, currentRow 应该变大。

考虑一下之前的示例, reverse 最初是 false ,因此 currentRow 计数继续变大。一旦我们到达底行, reverse 就被设置为等于 true ,此时 currentRow 计数继续变小。

因此,在 for 循环中,我们可以检查 reverse 是 true 还是 false。如果为 false,那么我们可以增加 currentRow 。否则,我们可以递减 currentRow

ini 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  let rows = [];
  let currentRow = 0;
  let reverse = false;
  let result = "";

  for (let i = 0; i < numRows; i++) {
    rows[i] = [];
  }

  for (let i = 0; i < s.length; i++) {
    rows[currentRow].push(s[i]);
    if (reverse === false) {
      currentRow++;
    } else {
      currentRow--;
    }

    //...
  }

  //...
}

我们在 for 循环中要做的最后一件事是检查我们是在最后一行还是在第一行。在这两种情况下,我们都希望朝着与刚才相反的方向前进,因此我们可以将 reverse 设置为等于 !reverse

ini 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  let rows = [];
  let currentRow = 0;
  let reverse = false;
  let result = "";

  for (let i = 0; i < numRows; i++) {
    rows[i] = [];
  }

  for (let i = 0; i < s.length; i++) {
    rows[currentRow].push(s[i]);
    if (reverse === false) {
      currentRow++;
    } else {
      currentRow--;
    }

    if (currentRow === numRows - 1 || currentRow === 0) {
      reverse = !reverse;
    }
  }

  //...
}

一旦 for 循环执行完毕,我们将得到多个数组。我们希望将每个数组转换为字符串,然后将这些字符串相互添加。

为此,我们可以在 rows 中的每一行调用 .forEach() 。对于每一行,我们可以使用 .join() 将其转换为字符串。然后我们可以将每个字符串添加到 result 中。最后,在 forEach 方法之外,我们可以返回结果。

ini 复制代码
function convert(s, numRows) {
  if (numRows === 1 || s.length < numRows) {
    return s;
  }
  let rows = [];
  let currentRow = 0;
  let reverse = false;
  let result = "";

  for (let i = 0; i < numRows; i++) {
    rows[i] = [];
  }

  for (let i = 0; i < s.length; i++) {
    rows[currentRow].push(s[i]);
    if (reverse === false) {
      currentRow++;
    } else {
      currentRow--;
    }

    if (currentRow === numRows - 1 || currentRow === 0) {
      reverse = !reverse;
    }
  }

  rows.forEach((row) => {
    result += row.join("");
  });

  return result;
}

如果您对如何解决此问题有任何疑问或其他想法,请在评论中告诉我!

相关推荐
莫叫石榴姐28 分钟前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
茶猫_1 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
肥猪猪爸3 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
readmancynn4 小时前
二分基本实现
数据结构·算法
萝卜兽编程4 小时前
优先级队列
c++·算法
盼海4 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步4 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
Rstln5 小时前
【DP】个人练习-Leetcode-2019. The Score of Students Solving Math Expression
算法·leetcode·职场和发展
芜湖_5 小时前
【山大909算法题】2014-T1
算法·c·单链表
珹洺5 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode