6. Z 字形變換

將一個(gè)給定字符串 s 根據(jù)給定的行數(shù) numRows 签钩,以從上往下娜搂、從左到右進(jìn)行 Z 字形排列放典。
比如輸入字符串為 "PAYPALISHIRING" 行數(shù)為 3 時(shí)辽幌,排列如下:

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

之后忠蝗,你的輸出需要從左往右逐行讀取现横,產(chǎn)生出一個(gè)新的字符串,比如:"PAHNAPLSIIGYIR"阁最。
請你實(shí)現(xiàn)這個(gè)將字符串進(jìn)行指定行數(shù)變換的函數(shù):
string convert(string s, int numRows);

第一種算法

自己沒看答案前戒祠,自己寫的,主要思路是:根據(jù)給定的字符串的長度和行數(shù)速种,算出一共多少列姜盈,然后將字符串再按照要求按列依次填入二維數(shù)組中,最后再按照行進(jìn)行讀取字符串配阵。

代碼如下馏颂,附有詳細(xì)的注釋:

def convert1(s, numRows):

    # 如果為1行,就直接返回原字符串
    if numRows == 1:
        return s

    # 記錄字符串長度
    n = len(s)
    # 行數(shù)
    row = numRows
    # 計(jì)算列數(shù)
    # 假設(shè)每row+(row-2)個(gè)字符為一組棋傍,這一個(gè)組的字符個(gè)數(shù)表示為:
    g_nums = row + (row - 2)
    # 那么這一組所占的列數(shù)為
    g_column = 1 + (row - 2)
    # 計(jì)算字符串中共有多少個(gè)組
    gs = n // g_nums
    # 余下的字符個(gè)數(shù)
    rest_num = n % g_nums
    # 計(jì)算剩下的不夠一組的字符占多少列救拉,默認(rèn)為0
    o_column = 0
    # 余下的字符個(gè)數(shù)小于等于行數(shù),剛好占一列
    if 1 <= rest_num <= row:
        o_column = 1
    # 余下的字符個(gè)數(shù)大于行數(shù)瘫拣,列數(shù)等于余下的個(gè)數(shù)減去行數(shù) +1
    elif rest_num > row:
        o_column = 1 + (rest_num - row)

    # 計(jì)算總的列數(shù)
    column = gs * g_column + o_column

    # 創(chuàng)建二維數(shù)組亿絮,沒有字符的,用"*"占位
    # 不能[["*"] * column] * row 這么創(chuàng)建,因?yàn)槔锩婷總€(gè)元素沒有自己的存儲空間
    arr = [["*"] * column for _ in range(row)]
    # 先是一列一列的按列遍歷派昧,依次"Z"字形填入字符串
    # 記錄遍歷到第幾組數(shù)據(jù)黔姜,默認(rèn)為0
    for j in range(column):
        for i in range(row):
            # 當(dāng)在完整的一個(gè)組時(shí)
            if j < gs * g_column:
                # 第一個(gè)條件:當(dāng)整列都有數(shù)據(jù)的列時(shí)
                # 第二個(gè)條件:當(dāng)一列只有一個(gè)數(shù)據(jù)時(shí),找規(guī)律有如下關(guān)系
                if j % g_column == 0 or i == (g_column - j % g_column):
                    arr[i][j] = s[0]
                    # 每次賦值后蒂萎,將賦值的那個(gè)字符舍棄秆吵,這樣每次都是拿第一個(gè)字符
                    s = s[1:]
            # 當(dāng)余下的不夠一個(gè)組時(shí)
            else:
                # 賦值時(shí)要保證字符串還有字符
                # 余下的一組中的第一列或者其他列時(shí)
                if len(s) > 0 and ((j - gs * g_column) == 0 or i == (g_column - j % g_column)):
                    arr[i][j] = s[0]
                    # 如果字符串為空了,就退出遍歷
                    s = s[1:]
                    if len(s) == 0:
                        break

    # 按行讀取字符串
    # 記錄讀取后的字符串
    rs = ""
    for i in range(row):
        for j in range(column):
            if arr[i][j] != "*":
                rs += arr[i][j]

    return rs

第二種方法

參考力扣官方答案和精選答案五慈,我們可以從左到右迭代 s纳寂,將每個(gè)字符添加到合適的行〔虺牛可以使用當(dāng)前行和當(dāng)前方向這兩個(gè)變量對合適的行進(jìn)行跟蹤烈疚。只有當(dāng)我們向上移動(dòng)到最上面的行或向下移動(dòng)到最下面的行時(shí),當(dāng)前方向才會(huì)發(fā)生改變聪轿。


效果圖

代碼如下爷肝,附有詳細(xì)注釋:

def convert2(s, numRows):

    # 如果行數(shù)等于1,就直接返回原字符串
    if numRows == 1:
        return s

    # 可能存在字符串的長度比給的行數(shù)小陆错,那么只需要字符串長度的行就可以了
    row = min(numRows, len(s))
    # 聲明一個(gè)字符串?dāng)?shù)組灯抛,用于記錄每行的字符串
    row_strs = ["" for _ in range(row)]
    # 默認(rèn)當(dāng)前行為0,即第一行
    current_row = 0
    # 記錄是不是方向向下音瓷,默認(rèn)為false
    going_down = False

    # 遍歷字符串对嚼,將每個(gè)字符加到合適的行
    for c in s:
        row_strs[current_row] += c
        # 當(dāng)在第一行或者最后一行時(shí),改變方向
        if current_row == 0 or current_row == row - 1:
            going_down = not going_down
        # 如果going_down為true绳慎,當(dāng)前行+1纵竖,否則-1
        current_row += 1 if going_down else -1

    # 將數(shù)組拼接成字符串,即是要求的字符串
    return "".join(row_strs)
復(fù)雜度分析
  • 時(shí)間復(fù)雜度 O(N) :遍歷一遍字符串 s杏愤;
  • 空間復(fù)雜度 O(N) :各行字符串共占用 O(N) 額外空間靡砌。

第三種方法

參考力扣精選答案,采用了數(shù)學(xué)規(guī)律法珊楼,即是找出數(shù)學(xué)規(guī)律通殃,然后按行訪問直接拼接成最終需要的字符串。

規(guī)律如下:
我們先假定有 numRows=4 行來推導(dǎo)下厕宗,其中 2numRows-2 = 6 , 我們可以假定為 step=2numRows-2 画舌,我們先來推導(dǎo)下規(guī)則:

第0行: 0 - 6 - 12 - 18
==> 下標(biāo)間距 6 - 6 - 6 ==> 下標(biāo)間距 step —— step —— step

第1行: 1 - 5 - 7 - 11 - 13
==> 下標(biāo)間距 4 - 2 - 4 - 2 ==> 下標(biāo)間距step-2 * 1(行) ——2 * 1(行)——step-2 * 1(行)——2 * 1(行)

第2行: 2 - 4 - 8 - 10 - 14
==> 下標(biāo)間距 2 - 4 - 2 - 4 ==> 下標(biāo)間距step-2 * 2(行)——2 * 2(行)——step-2 * 2(行)——2 * 2(行)

第3行:3 - 9 - 15 - 21
==> 下標(biāo)間距間距 6 - 6 - 6 ==>下標(biāo)間距step - step - step

可以得出以下結(jié)論:

  • 起始下標(biāo)都是行號
  • 第0層和第numRows-1層的下標(biāo)間距總是step 。
  • 中間層的下標(biāo)間距總是step-2行數(shù)已慢,2行數(shù)交替曲聂。
  • 下標(biāo)不能超過len(s)-1

代碼如下:

def convert3(s, numRows):
    if numRows == 1: return s

    res = ""  # 聲明一個(gè)返回的字符串
    step = numRows * 2 - 2  # 下標(biāo)間距
    index = 0  # 記錄s的下標(biāo),從0開始
    n = len(s)  # 字符串長度
    add = 0  # 真實(shí)的下標(biāo)間距

    for i in range(numRows):  # i 表示行號
        index = i
        add = i * 2
        while index < n:  # 當(dāng)下標(biāo)超出字符串長度就計(jì)算下一層
            res += s[index]  # 當(dāng)前行的第一個(gè)字符
            add = step - add  # 第一次的間距是step - 2*i蛇受,第二次是2*i
            # 第0行和最后一行使用step間距句葵,其他行都使用add間距
            if i == 0 or i == numRows - 1:
                index += step
            else:
                index += add
    return res  # 返回結(jié)果字符串

力扣答案傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厕鹃,一起剝皮案震驚了整個(gè)濱河市兢仰,隨后出現(xiàn)的幾起案子乍丈,更是在濱河造成了極大的恐慌,老刑警劉巖把将,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轻专,死亡現(xiàn)場離奇詭異,居然都是意外死亡察蹲,警方通過查閱死者的電腦和手機(jī)请垛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洽议,“玉大人宗收,你說我怎么就攤上這事⊙切郑” “怎么了混稽?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長审胚。 經(jīng)常有香客問我匈勋,道長,這世上最難降的妖魔是什么膳叨? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任洽洁,我火速辦了婚禮,結(jié)果婚禮上菲嘴,老公的妹妹穿的比我還像新娘饿自。我一直安慰自己,他們只是感情好龄坪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布昭雌。 她就那樣靜靜地躺著,像睡著了一般悉默。 火紅的嫁衣襯著肌膚如雪城豁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天抄课,我揣著相機(jī)與錄音唱星,去河邊找鬼。 笑死跟磨,一個(gè)胖子當(dāng)著我的面吹牛间聊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抵拘,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼哎榴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尚蝌,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤迎变,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后飘言,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衣形,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年姿鸿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谆吴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苛预,死狀恐怖句狼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情热某,我是刑警寧澤腻菇,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站苫拍,受9級特大地震影響芜繁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绒极,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一骏令、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垄提,春花似錦榔袋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至审丘,卻和暖如春吏够,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滩报。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工锅知, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脓钾。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓售睹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親可训。 傳聞我的和親對象是個(gè)殘疾皇子昌妹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 題目描述: 將一個(gè)給定字符串根據(jù)給定的行數(shù)捶枢,以從上往下、從左到右進(jìn)行 Z 字形排列飞崖。比如輸入字符串為 "LEETC...
    LeeYunFeng閱讀 941評論 0 50
  • 題目描述: 將一個(gè)給定字符串 s 根據(jù)給定的行數(shù) numRows 烂叔,以從上往下、從左到右進(jìn)行 Z 字形排列蚜厉。比如輸...
    vincewi閱讀 205評論 0 0
  • 點(diǎn)擊 這里[http://wechat.peterxx.com/qr_code_promote.html] 可以查...
    水三葉的刷題日記閱讀 233評論 0 0
  • 6. Z 字形變換 題目 將一個(gè)給定字符串根據(jù)給定的行數(shù)长已,以從上往下畜眨、從左到右進(jìn)行 Z 字形排列昼牛。比如輸入字符串為...
    索毅閱讀 223評論 0 0
  • 題目 將一個(gè)給定字符串根據(jù)給定的行數(shù),以從上往下康聂、從左到右進(jìn)行 Z 字形排列贰健。比如輸入字符串為 "LEETCODE...
    玖月晴閱讀 151評論 0 0