Check this out

Problem description

The string PAYPALISHIRING is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

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

And then read line by line: PAHNAPLSIIGYIR

Idea

When you finish reading the problem description section, many solutions might come to mind. However, for every problem, there is usually a core idea behind it.
It’s not about the code itself. Once you grasp the underlying idea, you’re good to go, and the code becomes secondary.

Look at this one, one more time PAYPALISHIRING

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

You start to read P and then move down to read A, and continue down to read Y. Each time you move down, you’re progressing row by row —Row 1, Row 2, Row 3, and so on until Row n - 1 Row 1, 2 and 3 and so on until row n - 1. For each row, add the current character to the answer. For each row, you add the current character to the answer.

Once you reach to the end of the road. You start moving back up, So for this problem, you alternate between moving down and up, down and up and so on. However, it’s important to keep track of the current row and whether you need to go up or down.

For instance: [””, “”, “”]. Push the current character to the first row:

["P", "", ""]

Move to the next character(Move down):

["P", "A", ""]
["P", "A", "Y"]

At this point, you need to go up.

["P", "AP", "Y"]
["PA", "AP", "Y"]

Just like this.

pub fn convert(s: String, num_rows: i32) -> String {
    if num_rows == 1 || s.len() <= num_rows as usize {
        return s;
    }

    // Keep track the current row
    let mut cur_row = 0;
    // Use to decide whether we need to move up or down
    let mut going_down = false;

    let mut rows: Vec<String> = vec![String::new(); num_rows as usize];

    for c in s.chars() {
        // Push the current character to the current row
        rows[cur_row].push(c);

        // When cur_row is 0, move down. Otherwise, move up
        if cur_row == 0 || cur_row == (num_rows - 1) as usize {
            going_down = !going_down;
        }
        // Continue move down
        if going_down {
            cur_row += 1;
        } else {
            // Continue move up
            cur_row -= 1;
        }
    }

    rows.concat()
}