乘風破浪:LeetCode真題_006_ZigZag Conversion
阿新 • • 發佈:2019-01-02
乘風破浪:LeetCode真題_006_ZigZag Conversion
一、前言
到這裡我們對基本的問題有了一定的理解,其中字串的操作一直是一個比較困難的問題,這一點我們需要認真對待,採用合理的方案去解決問題。下面我們就看看將字串按照某種格式排列之後再按行輸出的問題。
二、ZigZag Conversion
2.1 問題理解
2.2 分析以解決問題
看到這樣的問題我們最直接的想法就是構造一個二維陣列,初始化成某種字元,然後按照題目給定的規則進行填充,填充完成之後按行進行遍歷,將結果拼湊起來輸出出去。這種方法複雜度為O(n~2)。因此我們進行優化,採用StringBuilder這樣的結構來直接進行儲存,能夠將時間複雜度縮小到O(n)。
下面是官方的解法:
1 class Solution { 2 public String convert(String s, int numRows) { 3 4 if (numRows == 1) return s; 5 6 List<StringBuilder> rows = new ArrayList<>(); 7 for (int i = 0; i < Math.min(numRows, s.length()); i++)8 rows.add(new StringBuilder()); 9 10 int curRow = 0; 11 boolean goingDown = false; 12 13 for (char c : s.toCharArray()) { 14 rows.get(curRow).append(c); 15 if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; 16 curRow += goingDown ? 1 : -1;17 } 18 19 StringBuilder ret = new StringBuilder(); 20 for (StringBuilder row : rows) ret.append(row); 21 return ret.toString(); 22 } 23 }
我們的演算法:
public class Solution { /** * 題目大意 * 輸入一個字串和指定的行數,將字元以Z字型輸出。 * * 解題思路 * 計算出字元的最大列數,根據列數和行數建立一個一維陣列,再計算每個字元中一維陣列中的位置, * 再對一維陣列中的字元進行緊湊操作,返回結果。 * </pre> * * @param s * @param nRows * @return */ public String convert(String s, int nRows) { if (s == null || s.length() <= nRows || nRows == 1) { return s; } int index = s.length(); int rowLength = 0; // 計算行的長度,包括最後換行字元 int slash = nRows - 2; // 一個斜線除去首尾所佔用的行數 while (index > 0) { // 豎形的一列 index -= nRows; rowLength++; // 斜著的列數 for (int i = 0; i < slash && index > 0; i++) { rowLength++; index--; } } char[] result = new char[nRows * rowLength]; // 儲存結果的陣列,最後一列用於儲存換行符 for (int i = 0; i < result.length; i++) { // 初始化為空格 result[i] = ' '; } int curColumn = 0; // 當前處理的行數 index = 0; while (index < s.length()) { // 處理豎線 for (int i = 0; i < nRows && index < s.length(); i++) { result[rowLength * i + curColumn] = s.charAt(index); index++; } curColumn++; // 處理斜線 for (int i = nRows - 2; i > 0 && index < s.length(); i--) { result[rowLength * i + curColumn] = s.charAt(index); curColumn++; index++; } } // 對字元陣列進行緊湊操作 index = 0; while (index < s.length() && result[index] != ' ') { // 找第一個是空格的字元位置 index++; } int next = index + 1; while (index < s.length()) { while (next < result.length && result[next] == ' ') { // 找不是空格的元素 next++; } result[index] = result[next]; index++; next++; } return new String(result, 0, index); } }
這樣的演算法其實就是笨辦法了,首先計算出虛擬的二維陣列需要的空間大小,然後實際上(物理上)用一維陣列來表示,並且初始化為空,之後將源字串的字元按照規則填到虛擬的二維陣列中,其實是一維陣列,最後將一維陣列中的空格去除掉就得到了想要的結果,顯然是一個O(n~2)的演算法,沒有官方的好。
三、總結
通過這樣的一個例子,我們可以發現往往我們的原始想法都是暴力法,按部就班的來,只要稍微的優化一下就能變成更好的方法,得到更優質的結果,寫更少的程式碼。