6. Z字形變換

一、題目原型:

將字符串 "PAYPALISHIRING" 以Z字形排列成給定的行數(shù):
輸入: s = "PAYPALISHIRING", numRows = 3
輸出: "PAHNAPLSIIGYIR"
輸入: s = "PAYPALISHIRING", numRows = 4
輸出: "PINALSIGYAHRPI"
實(shí)現(xiàn)一個將字符串進(jìn)行指定行數(shù)變換的函數(shù):
string convert(string s, int numRows);

二、題目意思剖析:

 numRows = 3
 P   A   H   N
 A P L S I I G
 Y   I   R

 numRows = 4
 P      I       N
 A   L  S    I  G
 Y A    H  R
 P      I

三、解題思路:

3.1. 將原字符串按照“z字轉(zhuǎn)換規(guī)律”保存進(jìn)一個二維數(shù)組
3.2.將該二維數(shù)組橫豎對調(diào),得到最后的二維數(shù)組
3.3.用字符串拼接得到最后的答案

核心思路:找規(guī)律,找關(guān)鍵的幾個數(shù)據(jù)和numRows、字符串總長度之間的關(guān)系。
下圖中方框內(nèi)表示一個單元格。


筆記思路
第一步:能夠看出,這個排列是由一個個單元格(相同的排列)組成。
 P      I       N
 A   L  S    I  G
 Y A    H  R
 P      I
其中,單元格是
 P
 A   L
 Y A
 P
第二步:算出每一個單元所包含的字符個數(shù)

很簡單可以看出,每個單元是由最長的那一列+中間的那幾個字符。
而中間那些字符,剛好是除去最上面和最下面的那些。
所以:

let letterCount = numRows + (numRows - 2)
第三步:每個單元格包含的列數(shù)

1表示是行數(shù)最大那一列,(numRows - 2)是中間過渡的那幾列

let cols: Int = 1 + (numRows - 2)
第四步:總共有多少個單元格
var count: Int = 0
while letterCount*count <= letters.count {
    
    count = count + 1
}
// 因?yàn)樽詈骳ount會再次累加1,所以需要減1.
count = count - 1
第五步:總共列數(shù)
// 最終列數(shù)
var allCols: Int = 0
// 余數(shù):比如字符長度為17,17 % 6 = 5
let remainder = letters.count % letterCount
if remainder == 0 { // 說明剛好有整數(shù)個單元格
    allCols = count * cols
}else if remainder >= numRows && remainder < letterCount { 
    //如果余數(shù)大于或者行數(shù),并且小于一個單元格所包含的最大字符數(shù),allCols = 前面整數(shù)個的單元格列數(shù) + 1 + (余數(shù) - numRows)
    allCols = count * cols + 1 + (remainder - numRows)
}else {
    // 比如上面的例子, PAYPALISHIRING中,結(jié)果余數(shù) = 14%6 = 2,2 < numRows,所以allCols =  前面整數(shù)個的單元格列數(shù) + 1
    allCols = count * cols + 1
}
// 1.前二維數(shù)組
var allConvert = dim(allCols, dim(numRows, "*"))
var index: Int = 0 // 總字符串索引
for i in 0..<allCols {
    // i % cols,余數(shù) - 指的是字母離底部多長。
    if i % cols == 0 { // 當(dāng)余數(shù)為0時,就是最長列的時候。
        var convert: [String] = Array.init(repeating: "*", count: numRows)
        var j: Int = 0
        while index < letterCount * (i/cols + 1) && index < letters.count && j < numRows {
            convert[j] = letters[index]
            allConvert[i] = convert
            index = index + 1
            j = j + 1
        }
    }else { // 其他時候,就是用( 最大行數(shù) - 1 - 余數(shù) )
        var convert: [String] = Array.init(repeating: "*", count: numRows)
        convert[numRows - 1 - i%cols] = letters[index]
        allConvert[i] = convert
        index = index + 1
    }
}
print(allConvert)

這里需要一個創(chuàng)建二維數(shù)組的函數(shù)

// 創(chuàng)建二維數(shù)組
func dim<T>(_ count: Int, _ value: T) -> [T] {
    return [T](repeating: value, count: count)
}
第六步:橫豎置換
[["a", "b", "c", "d"],
 ["*", "*", "e", "*"],
 ["*", "f", "*", "*"],
 ["g", "h", "i", "j"],
 ["*", "*", "k", "*"],
 ["*", "l", "*", "*"]]
         變成
 [["a", "*", "*", "g", "*", "*"],
 ["b", "*", "f", "h", "*", "l"],
 ["c", "e", "*", "i", "k", "*"],
 ["d", "*", "*", "j", "*", "*"]]
// 將數(shù)組橫轉(zhuǎn),橫 -> 豎
// i[0,6) j[0,4)  ->   i[0,4) j[0,6)
var resultConverts = dim(numRows, dim(allCols, "*"))
for i in 0..<allCols {
    for j in 0..<numRows {
        resultConverts[j][i] = allConvert[i][j]
    }
}
第七步:拼接最終字符串
var result: String = ""
for i in 0..<numRows {
    for j in 0..<allCols {
        if resultConverts[i][j] != "*" {
            result.append(resultConverts[i][j])
        }
    }
}
print(resultConverts)
// result就是我們需要的答案

四、小結(jié)

總提交數(shù)
提交結(jié)果

思路完全正確的,就是耗時太長了,

有其他好的方法請極速留言,非常樂意一起探討。??
個人博客地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,203評論 3 119
  • 一、Java 簡介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計(jì)...
    子非魚_t_閱讀 4,562評論 1 44
  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 4,031評論 0 2
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,711評論 0 5
  • 今天很開心我加盟的事情終于著手開始了,而且剛好是朝著自己理想的方向在發(fā)展。感恩種子! 我近期的目標(biāo)是財富,我希望今...
    belivePossible閱讀 81評論 0 2

友情鏈接更多精彩內(nèi)容