LeetCode刷題筆記(六)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:

輸入: s = "PAYPALISHIRING", numRows = 3
輸出: "PAHNAPLSIIGYIR"

示例 2:

輸入: s = "PAYPALISHIRING", numRows = 4
輸出: "PINALSIGYAHRPI"
解釋:

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

解法1:這是一種很笨的方法,一開始一位規律會很難找,所以就想到用這種方法先做出來再說,

class Solution {
    public String convert(String s, int numRows) {
        if(numRows==1){
            return s;
        }
        StringBuilder str = new StringBuilder();
        List<char[]> list = new ArrayList<>();   //存儲整個的Z形的所有列
        int size = 0,len = s.length();
        for(int i = 0;i<len;i++){
            char[] chars = new char[numRows];    //存儲每一列的數據
            int remainder = i%(numRows-1);       //計算餘數,確定是否是整列
            for(int j = remainder==0?0:numRows-1-remainder;j<numRows-remainder;j++){   //如果是整列起點爲0,否則爲numRows-1-remainder
                chars[j] = s.charAt(size++);      //把列上的數據填到對應位置  
		if(size>=len){           //全部遍歷完跳出循環
                       break;
                };
            }
            list.add(chars);             //把每一列的數據加入集合
            if(size>=len){
                    break;
            };
        }
        for(int j = 0;j<numRows;j++){         //遍歷集合把爲默認值的char排除拼接起來
            for(int i = 0,length = list.size();i<length;i++){
                char[] chars = list.get(i);
                if(chars[j]!='\u0000'){
                    str.append(chars[j]);
                }
            }
        }
        return str.toString();
    }
}

這裏就是把每一列的數據都遍歷出來,以char數組的結構存到以list上,然後再通過遍歷把不是默認值的字符拼接起來,其實這裏如果用二維數組可能效果會好一點,在第二遍歷的時候空間複雜度會小一點;

時間複雜度:O(n)

空間複雜度:O(n^2)

解法2:

class Solution {
    public String convert(String s, int numRows) {
        int length = s.length();
        if(length<=1||numRows<=1){   //特殊參數情況處理
            return s;
        }
        StringBuilder str = new StringBuilder();
        
        for(int i = 0;i<numRows;i++){        //一行一行遍歷出字符
            int num = i;
            while(num<length){
                str.append(s.charAt(num));         
                if(i!=0&&i!=numRows-1&&num+2*(numRows-1-i)<length){   //如果不是第一行和最後一行,把單獨的一個字符拼接
                    str.append(s.charAt(num+2*(numRows-1-i)));
                }
                num += 2*(numRows-1);           //一個循環的等差
            }
        }
        return str.toString();  
    } 
}

這個方法直接遍歷拼接字符串,因爲我們可以找到對應的規律,先不考慮中間空缺的列,每一行對應的數對應的等差爲2*(numRows-1);接下來考慮特殊情況,即不在第一行和最後一行的時候,把多餘的一個字符加入進來,這裏也可以發現規律,如果行數爲num,則兩個的差值爲2*(numRows-1-num);所有直接遍歷拼接出字符串,比起第一種解法少了求出每一列的計算。而且空間複雜度也小很多。提交的數據第一個時間爲89ms,第二種解法爲39ms;

時間複雜度:O(n);

空間複雜度:O(n)



發佈了43 篇原創文章 · 獲贊 38 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章