? 模擬算法題往往不涉及復雜的數據結構或算法,而是側重于對特定情景的代碼實現,關鍵在于理解題目所描述的情境,并能夠將其轉化為代碼邏輯。所以我們在處理這種類型的題目時,最好要現在演草紙上把情況理清楚,再動手編寫代碼
1. Z字形變換
6. Z 字形變換 - 力扣(LeetCode)
????????對這道題,最容易想到的肯定是創建一個二維數組,像題目描述的那樣,以Z字形填充數組,然后再遍歷一遍數組,得到結果序列。然而這種做法比較復雜,而且時空復雜度都是比較高的,所以我們便來試著優化一下,找到更優秀的解法。一般而言,模擬題的優化往往都是根據找到的規律來編寫代碼,這道題也不例外。
????????由于題目最后僅要求我們寫出經過Z字形變換后得到的序列,所以我們其實是不需要真的創建數組的,只要能找到每一行的變換規律,編寫代碼,把每一行都加到要返回的字符串中就行了。
????????為了方便畫圖,我們畫的是要填入的字符串的下標,通過下圖我們可以發現,圖形中的第0行和最后一行填入的數規律是差不多的,假設公差為d,
則第0行:0,d,2d,……
最后一行:n-1,n-1+d,n-1+2d,……
? ? ? ? 對于第一行和最后一行,用簡單的數列知識就能得出d為2*n-2,至于中間的n-2行,看起來似乎有些復雜,但我們根本就沒必要理會填入的元素在二維數組中的位置,只要知道它們的值就行了,所以注意觀察數值規律,不難發現每一行的元素實際上可以被劃分為兩個數列的元素:
那么,現在我們已經可以找到了每一行的元素的規律,代碼實現也就壓根不需要二維數組了,希望大家看到這里,可以嘗試根據算法原理,自行編寫一下代碼,然后再來看答案。
class Solution {
public:string convert(string s, int numRows) {if(numRows == 1) return s;int d = 2 * numRows - 2;int r0 = 0, rn = numRows - 1;string res;while(r0 < s.size()){res += s[r0];r0 += d;}for(int k = 1; k < numRows - 1; k++){for(int i = k, j = d - k; i < s.size() || j < s.size(); i += d, j += d){if(i < s.size()) res += s[i];if(j < s.size()) res += s[j];}}while(rn < s.size()){res += s[rn];rn += d;}return res;}
};