[LeetCode] 006. Zigzag Conversion
-
date_range Mar. 27, 2019 - Wednesday info
- Problem (Medium)
- Approach 1: My Solution
- Approach 2: Improve the first solution
- Approach 3: Calculate index from original string to the new directly
- Idea
Problem (Medium)
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"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
- Input: s = “PAYPALISHIRING”, numRows = 3
- Output: “PAHNAPLSIIGYIR”
Example 2:
- Input: s = “PAYPALISHIRING”, numRows = 4
- Output: “PINALSIGYAHRPI”
Explanation:
P I N
A L S I G
Y A H R
P I
Approach 1: My Solution
Idea
Straight forward idea as stated in the problem:
- create a 2-D array with
numRows
rows andwidth
withd, wherewidth
is roughlylen(s) // (numRows-1) + 2
. - Put the string character by character into the 2-D array in the zigzag order.
- Concatenate the characters back to a new string based on the order stated in the problem.
Solution
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1
return s
width = len(s) // (numRows-1) + 2
m = [[None for i in range(width)] for j in range(numRows)]
i, j, k, up = 0, 0, 0, 0
while k < len(s):
m[i][j] = s[k]
if i == numRows-1:
up = 1
j += 1
if i == 0 and k != 0:
up = 0
j += 1
if up:
i -= 1
else:
i += 1
k += 1
res = ''
for row in m:
res += ''.join([i for i in row if i])
return res
Complexity
- Time: $O(n)$
- Space: $O(nr)$
Approach 2: Improve the first solution
Idea
Instead of initialize a 2-D array, just initialize a 1-D array in which each item represent the string for a row in the zigzag pattern.
Solution
class Solution2:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1:
return s
rows = [''] * numRows
cur_row, down = 0, 0
for c in s:
rows[cur_row] += c
if cur_row == 0 or cur_row == numRows-1:
down ^= 1
cur_row += 1 if down else -1
return ''.join([row for row in rows])
Complexity
- Time: $O(n)$
- Space: $O(n)$
Approach 3: Calculate index from original string to the new directly
Idea
Visit all characters in row 0 first, then row 1, then row 2, and so on …
Solution
class Solution2:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1: return s
res = ''
cycle_len = 2*numRows -2
for i in range(numRows):
for j in range(0, len(s) - i, cycle_len):
res += s[j+i]
if i != 0 and i != numRows -1 and j + cycle_len -i < len(s):
res += s[j + cycle_len -i]
return res
Complexity
- Time: $O(n)$
- Space: $O(n)$
KF