LeetCode 6. ZigZag Conversion題解

題目

6. ZigZag Conversion

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)

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

And then read line by line: “PAHNAPLSIIGYIR”

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

將一個給定字符串根據給定的行數,以從上往下、從左到右進行 Z 字形排列。

比如輸入字符串爲 “LEETCODEISHIRING” 行數爲 3 時,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N

之後,你的輸出需要從左往右逐行讀取,產生出一個新的字符串,比如:“LCIRETOESIIGEDHN”。

請你實現這個將字符串進行指定行數變換的函數:

string convert(string s, int numRows);

分析

依據題意,此題最關鍵的顯然就是找出所有字符所在的行數,這樣才能以行的順序將新的字符串返回。
爲了找出字母與行之間的關係,我們需要發掘一些規律:

思路一:移動方向

動態考慮Z型字符串在豎直方向上的產生過程,比如:
在這裏插入圖片描述
就是先從P開始,以↓表示向下走,以↑表示向上走,即爲P↓A↓Y↑P↑A↓L↓I……
不難發現箭頭的朝向是有規律的:
只有在字符到達第一行(curRow==1)或最後一行(curRow==numRows)時,方向纔會發生切換。

思路二:靜態分組

我們不考慮Z字型字符串的產生過程,直接考慮其最終結果,將之分組。
在這裏插入圖片描述
也就是每次當字符重新回到第一行時,會產生新的一組。
這樣分組以後,我們只需要知道每個字母在它所在的那組中的位置,就可以得到它的行數了。因爲每組的結構都是完全一樣的(都是兩列,且左列numRows行,右列numRows - 2行)。
而除了最後一組以外,每組的個數是groupNum = (2 * numRows - 2)(numRows > 1時才成立)。
在分組以後,對於每組,我們不難發現:(假設當前行爲 i,行從0開始數)
i == 0i == numRows-1時(也就是第一行和最後一行),該組內都只有一個字符滿足。
i爲其他值時,該組內總有兩個字符滿足。這兩個字符在組中的位置分別是 i 和 groupNum - i。
綜上所述,我們只需先將原先的字符串 s 進行分組,然後對於組進行遍歷,就可以得到每行的字符串了。


題解

Java實現思路一

import java.util.ArrayList;
import java.util.List;

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) return s;
        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < Math.min(numRows, s.length()); i++) rows.add(new StringBuilder());
        int curRow = 0;
        boolean goingDown = false;
        for (char c : s.toCharArray()) {
            rows.get(curRow).append(c);
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }
        StringBuilder ret = new StringBuilder();
        for (StringBuilder row : rows) ret.append(row);
        return ret.toString();
    }
}

C++實現思路一

class Solution {
    public:

    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        vector<string> rows (min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;
        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }
        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};

以上兩個都是LeetCode的官方題解。

Java實現思路二

import java.util.ArrayList;
import java.util.List;

public class Solution {

    public String convert(String s, int numRows) {
        StringBuilder returnString = new StringBuilder();
        if(numRows == 1)return s;
        int groupNum = numRows * 2 - 2;//一組的個數
        List<String> groups = new ArrayList<>();
        for(int i=0;i<s.length();i+=groupNum){//分組
            if(i + groupNum <= s.length()) {
                groups.add(s.substring(i, i + groupNum));
            }else{
                groups.add(s.substring(i,s.length()));
            }
        }
        for(int i=0;i<numRows;i++){//按行輸出,從第一行到最後一行
            for(String group:groups){
                if(i == 0){
                    //打印該組第一行(僅一個字符)
                    returnString.append(group.charAt(0));
                }
                else if(i == numRows - 1){
                    //打印該組最後一行(僅一個字符)
                    if(numRows - 1 < group.length()) {
                        returnString.append(group.charAt(numRows - 1));
                    }
                }else{
                    //打印該組其他行(兩個字符,index分別是i和groupNum-i)
                    if(i < group.length()) {//確保數組訪問不越界(也就是考慮到最後一組的特殊情況)
                        returnString.append(group.charAt(i));
                    }
                    if(groupNum-i < group.length()) {
                        returnString.append(group.charAt(groupNum-i));
                    }
                }

            }
        }
        return returnString.toString();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章