Zigzag Conversion
class Solution {
/**
* @param String $s
* @param Integer $numRows
* @return String
*/
function convert($s, $numRows) {
$len = strlen($s);
if ($numRows == 1 || $numRows >= $len) {
return $s;
}
// Массив для хранения строк
$finalString = '';
$rows = array_fill(0, $numRows, "");
$currentRow = 0;
$goingDown = false; // Направление (идем вниз или вверх по строкам)
// Пройдем по каждому символу строки
for ($i = 0; $i < $len; $i++) {
// Добавляем символ в текущую строку
$rows[$currentRow] .= $s[$i];
// Если находимся в первой или последней строке, меняем направление
if ($currentRow == 0 || $currentRow == $numRows - 1) {
$goingDown = !$goingDown;
}
// Изменяем строку в зависимости от направления
$currentRow += $goingDown ? 1 : -1;
}
// Собираем все строки в один результат
foreach ($rows as $row) {
$finalString .= $row;
}
return $finalString;
}
}
Давайте подробно разберем, как работает алгоритм, особенно на примерах, с акцентом на вычисления и переходы по строкам в зигзагообразном паттерне.
Основной принцип
- Мы записываем строку в несколько строк, двигаясь сначала сверху вниз, затем снизу вверх.
- Для каждого символа строки мы добавляем его в одну из строк, определяемую текущей позицией.
- Когда мы достигаем верхней или нижней строки, меняем направление.
Пример 1: "PAYPALISHIRING"
с numRows = 3
P A H N
A P L S I I G
Y I R
Как это работает:
- Строка:
"PAYPALISHIRING"
, numRows = 3. - Массив для строк: Массив из 3 строк, которые мы будем заполнять символами. Изначально все строки пусты:
rows = ["", "", ""]
- Мы начинаем с первого символа, который добавляется в первую строку (индекс 0):
rows[0] = "P"
- Переходим ко второму символу, который добавляется во вторую строку (индекс 1):
rows[1] = "A"
- Переходим к третьему символу, который добавляется в третью строку (индекс 2):
rows[2] = "Y"
- Теперь нам нужно вернуться в строку 1, и далее мы снова идем вниз. Следующий символ "P" добавляется в строку 1:
rows[1] = "AP"
- После этого добавляем символ в строку 0:
rows[0] = "PA"
- Потом добавляем символ в строку 1, и так далее. Весь процесс продолжается по тому же принципу — сначала вниз, потом вверх, и так по циклу.
Визуально:
Заполнение строк происходит так:
Позиция: 0 1 2 3 4 5 6 7 8 9 10 11 12
Символы: P A Y P A L I S H I R I N
rows[0]: P A H N
rows[1]: A P L S I I G
rows[2]: Y I R
После того как все символы будут записаны в строки, мы просто их собираем:
rows[0] = "PAHN"
rows[1] = "APLSIIG"
rows[2] = "YIR"
Результат: "PAHNAPLSIIGYIR"
Пример 2: "mother"
с numRows = 2
m o t h e r
Пошаговое объяснение:
- Строка:
"mother"
, numRows = 2. - Массив для строк:
rows = ["", ""]
-
Заполняем строки, двигаясь сверху вниз и потом вверх:
-
Первый символ "m" идет в строку 0.
rows[0] = "m"
- Второй символ "o" идет в строку 1.
rows[1] = "o"
- Третий символ "t" идет обратно в строку 0.
rows[0] = "mt"
- Четвертый символ "h" идет в строку 1.
rows[1] = "oh"
- Пятый символ "e" идет снова в строку 0.
rows[0] = "mte"
- Шестой символ "r" идет в строку 1.
rows[1] = "ohr"
Теперь мы собираем строки:
rows[0] = "mte"
rows[1] = "ohr"
Результат: "mohrte"
Пример 3: "A"
с numRows = 1
Для строки из одного символа мы не делаем никаких изменений, просто возвращаем исходную строку.
Результат: "A"
Пояснение по шагам
- Мы начинаем с первого символа строки и добавляем его в строку с индексом
currentRow
. - После каждого символа проверяем:
- Если мы находимся в верхней или нижней строке (
currentRow == 0 || currentRow == numRows - 1
), меняем направление. - Направление меняется с "вниз" на "вверх", и наоборот.
- Когда все символы будут обработаны, строки из массива собираются в один результат.
Заключение
Этот алгоритм работает эффективно, даже если вы не хотите использовать стандартные зигзагообразные способы с массивами или другими сложными структурами данных. Алгоритм опирается на простое управление направлением и текущей строкой для создания желаемого зигзагообразного паттерна.