leetCode 6. ZigZag Conversion解题心得

最近正在学习Python,因为对语言的不熟练,所以打算刷题来使自己的语言掌握的更充分。在leetCode上看见了这么一道题

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)

就是ZigZag 首先还是用图来说一下原理吧
首先就用简单的'0123456789012345678'来演示下


示意图.png

就是将数字按上图排放,以竖列形式拜访


读取示意图.png

读取的时候从左向右读所以最终读取出来的文字是"0482613579135726048"
读取方式也知道了,下面就该开始代码部分了。
首先我的思路就是按照图片方式,准备一个二维数组。
#这里是判断如果特殊情况,若给定行数过大或过下,直接做特殊处理
  if numRows == 2:
    array_1 = []
    array_2 = []
    for i in range(0,len(s)):
      if i % 2 == 0:
        array_1.append(s[i])
      else:
        array_2.append(s[i])
      str = ''.join(array_1)
      str += ''.join(array_2)
      return str
   elif numRows <= 1:
            return s
   elif numRows >= len(s):return s
列数为4时候快照.png
#首先根据上图中方框部分算出,当numRows = 4时候重复部分的数量为6,当numRows = 3时重复部分的字母数量为4,可以在纸上画出当numRows = 5时重复部分的字符数量为8,所以计算可得重复部分的数量随numRows变化的数量就是numRows + numRows - 2
#count 为剩余部分有多少个字符
  count = len(s) % (numRows + numRows - 2)
#index为总共有多少个块
  index = len(s) // (numRows + numRows - 2)
#i为这个块中有多少列观察可得,numRows 数量单独占一列,剩下的一个字符占一列,所以最终每个块中有1 + numRows - 2列
  i = index * (1 + numRows - 2)
#j为剩余部分字符减去列数后剩余数量+1列
  j = (count - numRows + 1) if count > numRows else 1
#total为总列数
  total = i + j
  array = []

接下来就该开始循环给对应字符放入数组中了

  for real_i in range(0,total):
#创建每列的数组
      real_array = []
#这个判断为判断是否为该块的第一列(第一列为字母数量为numRows,其他列数字母数量为1)
      if real_i % (numRows - 1) == 0:
#计算该块起始位置
        g = 2 * real_i
#循环添加字符进入数组
          for letter in range(g, g + numRows if g + numRows < len(s) else len(s)):
            real_array.append(s[letter])
      else:
#计算该列在该块中的位置
        real_index_i = real_i % (numRows - 1)
#计算这个字符处于这个数组中的第几个位置
        real_index_j = 2 * (real_i - real_index_i) + numRows
#取出字母
        letter = s[real_index_i + real_index_j - 1]
#循环向数组中加入字符
        for x in range(0,numRows):
          if x == (numRows - 1 - real_index_i):
            real_array.append(letter)
          else:
            real_array.append(' ')
#将这个数组加入总数组
      array.append(real_array)

这步做完了后,所有操作基本已经算是完成,这个已经算是完成一多半
最后就剩下拼凑字符串了

    str = ''
    i = 0
#取数组和平时遍历数组方式不太一样,外层的循环实际上是用来遍历每个数组的角标i的位置的
    while True:
      for sub_array in array:
        if len(sub_array) > i:
          real = sub_array[i]
#这个地方的判断是为了防止数字崩溃,因为当时用数字做的测试,将数字转换成字符
          if isinstance(real,int):
            str += '%d '%(real)
          else:
            str += real
#下面部分是为了方便打印出对应的格式的(真实提交测试时需要删去)
            str += ' '
        str += '\n'
        i += 1
      if i == numRows:
        break
    return str

经过测试提交,leetCode 给出的error是timeLimit,说明代码是可以正确计算出结果了,但是耗时非常长,复杂度至少是O(n*numRows),太复杂了,耗时主要是在从数组中取出对应字符的步骤,所以需要优化,最终决定优化的方式是将数组转化成字典,用key对应所在位置,直接优化复杂度为O(n3)

#首先是循环部分修改
    dic = {}
#real_i直接为所在位置的横坐标
    for real_i in range(0,total):
      if real_i % (numRows - 1) == 0:
        g = 2 * real_i
        for n in range(g, g + numRows if g + numRows < len(s) else len(s)):
#y为纵坐标
          index_y = letter - g
          index_x = real_i
          dic[index_x + index_y * (total)] = s[n]
      else:
        real_index_i = real_i % (numRows - 1)
        real_index_j = 2 * (real_i - real_index_i) + numRows
        letter = s[real_index_i + real_index_j - 1]
        index_y = numRows - 1 - real_index_i
        index_x = real_i
        dic[index_x + index_y * (total)] = letter

接下来就剩读取了,首先,现在key不是连续的,但是,咱们的位置排序却是从小到大排序的,所以,下一步的操作就是给key进行排序了,python有很强大的排序方法,就是sort

str = ''
i = 0
array = list(dic.keys())
array.sort()
for key in array:
  letter = dic[key]
  if isinstance(letter, int):
    str += '%d' % (letter)
  else:
    str += letter
return str

将修改后的代码重新提交测试,成功通过。应该还有更好的方法,就是直接计算出对应的角标位置,但是碍于时间有限,就先用这个方法偷偷懒啦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,050评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,538评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,673评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,622评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,047评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,974评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,129评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,893评论 0 209
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,654评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,828评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,297评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,619评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,326评论 3 243
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,176评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,975评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,118评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,909评论 2 278

推荐阅读更多精彩内容