目錄
🎈了解題意
🎈算法原理
🚩先處理第一行和最后一行
🚩再處理中間行
🎈實現代碼
🎈了解題意
大家看到這個題目的時候肯定是很迷茫的,包括我自己也是搞不清楚題目什么意思,我們靜下心來看看我來給大家說透徹這個題目的意思。
我們輸入字符串"ABCDEFGHIJKL",行數是四行時,我們是按照Z字形排列。先向下排四行,然后斜向上排列到四行之后,然后向下排列四行......。(我們用一塊一塊的方格來填字符)
然后我們輸出的是像數組一樣遍歷 輸出結果是 AGBFHLCEIKDJ 字符串。
🎈算法原理
我們舉例輸入的是? ?ABCDEFGHIJKMNOP? 這段字符串,我們輸出的字符串就是從第一行第一列遍歷到最后一行最后一列。
🚩先處理第一行和最后一行
我們從第一行分析,我們看到 AGM之間的距離 A和G之間的距離是6,G與M之間的距離是6,我們就可以看到對于第一行來說,我們只需要循環從0開始,每次+6,就給新字符串更新結果。6是相當于公差d=6,6是怎么來的呢?
我們的公差6其實相當于,將F向左移一列,然后倆列一共是8個元素,然后減去2個空格就是公差了那么我們就衍生一個公式 ?公差d=2n-2 (n代表行數),舉一個例子當然是不能足以證明結果,我們給n設定3行,我們看看第一行公差是不是d=2*3-2=4.
我們看到,d=2n-2,n等于3的時候d=4,公差是4,確實驗證了我們的猜想。所以第一行每個元素的相差的距離是2n-2的距離(n代表行數)
string ret;//定義個最終字符串結果int d=2*numRows-2,n=s.size();//公差為2n-2,n代表原字符串的長度//1.先處理第一行for(int i=0;i<n;i+=d)//每次都加上公差{ret+=s[i];//更新結果}
?同樣的,我們看到最后一行其實和第一行是同樣的原理。
//處理最后一行for(int i=numRows-1;i<n;i+=d){ret+=s[i];}
🚩再處理中間行
我們看到BHN綠色線指向的,B和H相差6,H和N相差6,和第一行和最后一行一樣的思路,那么我們中間的FL和EK紫色線畫的,我們看到F和L相差的結果也是6,EK相差的結果也是6,所以還是再循環的時候加上公差d,那么我們如何確定F和E下標的值呢?還是和上面一樣的,我們是如何計算公差的呢?移動數據。字符在哪一列,我們就看前面列數的總空格數減去空白格即可。
- G= 前面有3列一共有3*4=12格? 減去? 前面列數的空格數6 = 6 字符G的下標是處在原字符串下標6的位置
- F= 前面有2列一共有2*4=8格? 減去? 前面列數的空格數3? =5 字符F的下標是處在原字符串下標5的位置
那么F相當于2n-3=5(n等于4,三個空格),E相當于n-0=4 (n等于4,0格空格)
我們如何確定F和E的開始值呢?
對于第二行 F的下標是5,公差是6, 相當于6-1=5
對于第三行 E的下標是4 ,公差是6? ?相當于6-2=4
所以我們進行依次循環,處理中間行,從k=1開始,第二行的第二個元素是d-k,到k=2時,第三行的第三個元素是d-k,然后當k=n-1=3的時候就結束了,因為第四行是最后一行。
for(int k=1;k<numRows-1;k++){for(int i=k,j=d-k;i<n||j<n;i+=d,j+=d){if(i<n)ret+=s[i];if(j<n)ret+=s[j];}}
我們是先讓i對應的值先更新,然后再更新j對應的值,條件是i<n或者j<n,因為只要其中一個滿足的話,我們還是要更新結果。下面要進行判斷,否則就重復更新了。?
🎈實現代碼
class Solution {
public:string convert(string s, int numRows) {if(numRows==1)return s;string ret;int d=2*numRows-2,n=s.size();//1.先處理第一行for(int i=0;i<n;i+=d){ret+=s[i];}//2.處理中建行for(int k=1;k<numRows-1;k++){for(int i=k,j=d-k;i<n||j<n;i+=d,j+=d){if(i<n)ret+=s[i];if(j<n)ret+=s[j];}}//處理最后一行for(int i=numRows-1;i<n;i+=d){ret+=s[i];}return ret;}
};
開學壞,見面好。