給定乙個字串,找出不含有重複字元的最長子串的長度。
示例 1:
輸入: s = "paypalishiring", numrows = 3
輸出: "pahnaplsiigyir"
解釋:p a h n
a p l s i i g
y i r
示例 2:
輸入: s = "paypalishiring", numrows = 4輸出: "pinalsigyahrpi"
解釋:p i n
a l s i g
y a h r
p i
這道題有兩種解法,一種是利用數學表示式計算出行數與元素排布位置的聯絡,用數學表示式表達出,不過這並不是我們想要的最優解,或者說,他並不優雅,因為沒有體現出演算法的美感,只是單純的找規律了。
所以我們想,能不能不靠找規律,準備乙個陣列與之對應:
通過從左向右迭代字串,我們可以輕鬆地確定字元位於 z 字形圖案中的哪一行。
我們可以使用min
(numrows
,len(s
))
\text( \text, \text(s))
min(
numrows
,len(s
))個列表來表示 z 字形圖案中的非空行。
從左到右迭代 ss,將每個字元新增到合適的行。可以使用當前行和當前方向這兩個變數對合適的行進行跟蹤。
只有當我們向上移動到最上面的行或向下移動到最下面的行時,當前方向才會發生改變。
class
solution
string ret;
for(string row : rows) ret += row;
return ret;}}
;
以"paypalishiring"
numrows=3為例:
我們首先把行數,元素數兩者最小那個當做劃分區域(通常都是行數小),這樣我們就分成了numrows=3組,很自然,我們把前三個元素依次放到,第1、2、3組中,注意,當我們觸底(currows=3)時,需要回溯(減小currows),所以我們建立了變數goingdown
,來控制是向上還是向下。
而且只需要遍歷一次,下面以goingdown的改變來分組
依次類推,很容易明白其中規律
其實數學規律很容易想到,但是**可能可能不是很容易寫出來,但是上面的這種演算法,很直觀,為什麼不容易想到呢,我認為是思維受到了限制,我們很容易地就直接造出乙個與原陣列等長的陣列,乙個乙個往上去新增,但是我們可以先靠行分類,然後改變量值放入的順序。
本體值得注意的有
vectorrows(min(numrows, int(s.size())));
··· rows[currow] += c;
vector中的元素型別是string,這一點很巧妙,這樣只需要乙個加號,就能在結尾新增新字元。
goingdown = !goingdown;
currow += goingdown ? 1 : -1;
能把**寫到如此簡潔需要乙個過程,當然,簡單點的話可以寫乙個判斷來改變goingdown的值
最重要的思想還是通過控制currow的步進方向,來實現z字形變換
讓我們一起進步啊
LeetCode 6 Z字形變換
將字串 paypalishiring 以z字形排列成給定的行數 p a h n a p l s i i g y i r之後從左往右,逐行讀取字元 pahnaplsiigyir 實現乙個將字串進行指定行數變換的函式 string convert string s,int numrows 輸入 s pa...
leetcode 6 Z字形變換
將字串 paypalishiring 以z字形排列成給定的行數 p a h n a p l s i i g y i r之後從左往右,逐行讀取字元 pahnaplsiigyir 實現乙個將字串進行指定行數變換的函式 string convert string s,int numrows 示例 1 輸入...
LeetCode 6 Z字形變換
把整個問題拆解為 儲存 取 的兩個過程 通過觀察我發現的是,當numrows為3時,兩列之間的數字的數目為1 當numrows為4時,兩列之間的數字的數目為2,以此類推。那麼,可不可以將每一列都存起來 col 兩列之間的數字也存起來 gap 最後要輸出時再通過遍歷的方式拼接出結果呢?以題目中給的字串...