Z字形变换
题目:将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "LEETCODEISHIRING"
行数为 3 时,排列如下:
L C I R E T O E S I I G E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"
。
来源:https://leetcode-cn.com/problems/zigzag-conversion/
法一:自己的代码
思路:通过枚举输入字符串构成Z后的索引,找到索引的规律,首末行和其余行都是由数列构成,且公差一致,区别是首末行是单个的数列,而其余行是两个公差一致的交错数列构成,故问题便转化成了将若干个数列取前几项放入一个list中,由于输出的要求,必须是从第一行到最后一行逐一进行append,且append前要先判断数列索引是否超出的字符串的长度,得到str_index后,即可直接由索引找到对应的元素并输出
思路:通过枚举输入字符串构成Z后的索引,找到索引的规律,首末行和其余行都是由数列构成, 且公差一致,区别是首末行是单个的数列,而其余行是两个公差一致的交错数列构成, 故问题便转化成了将若干个数列取前几项放入一个list中, 但必须是从第一行到最后一行逐一进行append,且append前要先判断数列索引是否超出的字符串的长度, 得到str_index后,即可直接由索引找到对应的元素并输出 class Solution: def convert(self, str, numRows): if numRows == 1: # 1比较特殊 单独进行判断 print(str) else: str_index = [] for i in range(numRows): j = 0 # j用于记录Z中第一行和最后一行的公差倍数 k = 0 # 当不是首末行时,会有两个首项不同的数列,k用于记录Z中非首末行的公差倍数 tolerance = 2 * (numRows - 1) print(tolerance) if i == 0: while (j * tolerance) < len(str) and j < len(str): # str_index[j * tolerance] = j * tolerance str_index.append(j * tolerance) j = j + 1 print(str_index) elif i == (numRows-1): while ((numRows-1) + j * tolerance) < len(str): str_index.append((numRows-1) + j * tolerance) j = j + 1 print('kkkkkkkk') print(str_index) else: # tolerance_1 = tolerance - 1 - i * 2 # tolerance_2 = tolerance - 1 - (numRows - i) * 2 while (i + j * tolerance) < len(str): # print(i + j * tolerance) # print('公差是', tolerance) # print('i is:', i) # print('j is:', j) str_index.append(i + j * tolerance) j = j + 1 # 交错判断两个数列是否超出了len(str),由于两个数列是交错穿插的,所以第二个数列判断完后直接break while (tolerance - i + k * tolerance) < len(str): # tolerance - i * 2 是第二个数列的首项 str_index.append(tolerance - i + k * tolerance) k = k + 1 break print(str_index) print(str_index) final_str = [] for i in range(len(str)): final_str.append(str[str_index[i]]) print("".join(final_str)) if __name__ == '__main__': duixiang = Solution() s = "AB" print(len(s)) duixiang.convert( s, 1 ) # "PAYPALISHIRING" # 4
法二:
思路:仍然是找到数列的规律后,逐行进行判断,问题的关键仍然是如何确定首项及公差,特别是除首末行外其余行的第二个数列,其中第一个数列的最大值是由for i in range(j, l, count):所限定的,第二个数列的最大值由if temp < l 限定的。要学会for i in range(j, l, count)的写法
思路:仍然是找到数列的规律后,逐行进行判断,问题的关键仍然是如何确定首项及公差,特别是除首末行外其余行的第二个数列, 其中第一个数列的最大值是由for i in range(j, l, count):所限定的,第二个数列的最大值由if temp < l 限定的。 要学会for i in range(j, l, count)的写法 class Solution: def convert(self, s: str, numRows: int) -> str: if numRows == 1: return s count = 2 * numRows - 2 print(count) re_str = '' l = len(s) j = 0 while j < numRows: for i in range(j, l, count): # count是数列的公差 print('i is:', i) re_str += s[i] temp = i + count - 2 * j print('temp is:', temp) if temp < l and (temp % count) != 0 and temp != i: re_str += s[temp] print('re_str is:',re_str) j += 1 return re_str if __name__ == '__main__': duixiang = Solution() s = "LEETCODEISraefasfafasfasfdasfHIRING" print(duixiang.convert(s, 4))