1. 程式人生 > >6. Z字形變換(leetcode)

6. Z字形變換(leetcode)

將字串 "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"

解釋:

解決方案

方法一:暴力法

比如有一個字串 “0123456789ABCDEF”,轉為zigzag。 當numRows為2時: 0 2 4 6 8 A C E 1 3 5 7 9 B D F

當numRows為3時: 0    4    8    C 1 3 5 7 9 B D F 2    6    A    E

當numRows為4時: 0      6       C 1   5 7    B D 2 4   8 A     E 3      9        F

我們可以看到,除了第一行和最後一行中間沒有形成之字形的數字外,其餘都有,並且形成的黑色字元之間,列與列之間相鄰的兩個元素的index之差與行數是相關的,都是 2*rows - 2。因此,根據這一個特點,我們可以按順序找到所有的黑色元素在原字串中的位置。對於紅色字元的出現也是有規律的,每一個紅色字元的位置為 j + (2*rows - 2) - 2*i ,其中j為前一個黑色元素所處的列數,i為當前的行數。當我們知道所有黑色元素和紅色元素位置的正確演算法,我們就可以一次性的把它們按順序都加到新的字串裡面。其中程式碼如下:

class Solution {
public:
   string convert(string s, int numRows) {
       if(numRows <= 1)
           return s;
       int len = s.length();
       string res = "";
       int size = 2*numRows - 2;
       for(int i=0;i<numRows;i++)
       {
           for(int j=i;j<len;j+=size)
           {
               res += s[j];
               int temp = j + size - 2*i;
               if(i != 0 && i != numRows-1 && temp < len)
                   res += s[temp];
           }
       }
       return res;
   }
};

複雜度分析

  • 時間複雜度:O(n),每個索引被訪問一次。
  • 空間複雜度:O(n)。