Python - 2 approaches
Python O(n**2) / O(n) - matrix construction\n\nclass Solution:\n    def generate_matrix(self, s, rows, cols, N):\n        i = 0\n        m = [[None] * cols for 
Python O(n**2) / O(n) - matrix construction\n```\nclass Solution:\n    def generate_matrix(self, s, rows, cols, N):\n        i = 0\n        m = [[None] * cols for _ in range(rows)]\n        for r in range(rows):\n            for c in range(cols):\n                m[r][c] = s[i]\n                i += 1\n                if i >= N: return m\n                \n    def decipher_by_matrix(self, m, rows, cols, N):\n        i = 0        \n        result = []\n        \n        for c in range(cols):\n            ci, ri = c, 0\n            if i >= N: return result  \n            while ci < cols and ri < rows and i < N:\n                result.append(m[ri][ci])\n                ri += 1\n                ci += 1\n                i += 1\n                \n        return result  \n    \n    def decodeCiphertext(self, s: str, rows: int) -> str:\n        N = len(s)        \n        cols = N // rows\n        \n        m = self.generate_matrix(s, rows, cols, N)                \n        result = self.decipher_by_matrix(m, rows, cols, N)\n                                    \n        return \'\'.join(result).rstrip()\n```\n\nPython O(n)/O(1)\n```\nclass Solution:\n    def decodeCiphertext(self, s, rows):\n        cols, N, result = len(s) // rows, len(s), []\n        for col in range(cols):\n            for move in range(col, N, cols + 1):\n                result.append(s[move])                \n        return \'\'.join(result).rstrip()\n```
[]