1. 程式人生 > >依照特定軌跡遍歷字符串圖

依照特定軌跡遍歷字符串圖

blog vector ddc comm urn convert 三層 print key

題目大致是這樣的,
字符串“PAYPALISHIRING”的一種“之”字型路線是這樣的:
技術分享
假設一行一行的讀寫,就是PAHNAPLSIIGYIR。

所以,假設輸入PAHNAPLSIIGYIR和3,就是橫著的字符串和層數,輸出N軌跡的字符PAYPALISHIRING。

首先想到的是怎樣 將輸入字符串。切割開來,比方上面是3層,分成3個字符串,這三個字符串一定是連續的
第一段+第二段+第三段
如今的難題是怎麽推斷每一段的長度。


將上面的圖抽象化
技術分享
就是這樣的,每個圓代表一個字符。這事實上是有規律的。

例如以下
技術分享
這樣每一層的個數和這個周期之間是有關系的
base=(字符總個數/(層數+層數-2))
第一層個數=base+x
最後一層=base+x
其它層=base×2+x。
技術分享


這裏面的x表示(如上圖)綠色的圓的補償,比方如以下4個綠色圓,
base=20/8=2
第一層=2+1=3;
第二層=2×2+1=5。
第三層=2×2+1=5;
第四層=2×2+1=5;
最後一層=2+0=2;
假設是以下這樣的情況
技術分享
事實上算法也是一樣的僅僅要對於補償x值修正就能夠了。本次就不討論這樣的情況了。


技術分享
到達這一步時,將之前的切割成了3部分,然後進行N軌跡遍歷,
初步方案是。給三個字符串編號1、2、3.然後依照12321232123的遍歷直到結束
所以如今須要解決的問題是,怎樣實現這樣的循環的遍歷。

這裏想到在cpu中有個寄存器用於決定地址是加一還是減一操作,所以借用這樣的思想。例如以下方案
技術分享


實現函數例如以下

string  convert(string text,int nRow)//text為輸入字符串 nRow是層數
{
 string r;
 vector <string> m;
 int arry[251]={0};
 int len=text.size();
 int s,c;
 s=len/(2*nRow-2);  //base數據
 c=len%(2*nRow-2);  //為上面綠色的個數
 for(int i=1;i<=nRow;++i)
 {
  if(i==1)    //計算第一層的個數
  {
   if(c>=1)
    arry[i]=s+1
; //arry的下標表述層數,內容為當前層的個數 else arry[i]=s; } else if(i==nRow) //計算最後一層的個數 { if(c>=nRow) arry[i]=s+1; else arry[i]=s; } else //中間層的個數 { if(c>=i&&) arry[i]=2*s+1; else arry[i]=2*s; } } m.resize(nRow+1); int loc; int base; base=0; for(int i=1;i<=nRow;++i) //依據每一層的個數,切割字符串 { base+=arry[i-1]; for(int j=0;j<arry[i];++j) { loc=j+base; m[i].push_back(text[loc]);//m[i]保存每一層的字符串。 } } int flag=0; //~0 addr++ 0 add-- int cnt=1; int* num=new int[nRow+1](); //以下是在切割完畢後的循環遍歷 int x,y; int tol=text.size(); while(1) { tol--; if(tol<0) break; x=cnt; y=num[cnt]; r.push_back(m[x][y]); num[cnt]++; if(cnt==nRow || cnt==1) flag=~flag; if(flag!=0) cnt++; else cnt--; } cout<<r<<endl; return r; }

依照特定軌跡遍歷字符串圖