leetcode第6题,采用动态规划的算法来完成。

Z字形变换

问题描述

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:(这里用#表示空格加以区分)

L # C # I # R # E T O E S I I G E # D # H # N #

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入: s = “LEETCODEISHIRING”, numRows = 3 输出: “LCIRETOESIIGEDHN”

示例 2:

输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: s = “LEETCODEISHIRING”, numRows = 4 输出: “LDREOEIIECIHNTSG” 解释: L # # D # # R E # O E # I I E C # I H # N T # # S # # G

思路1:遍历法

这里以c/c++语言来具体化

具体思路开始(可以参考下面几幅图)

  1. 创建一个字符串的动态数组vector < string > str(min(int(s.length()),numRows)),用来存放numRows个元素

  2. 循环时,动态数组的行数增加或减小,设置一个flag值用于转换方向,设置一个i值用于累加行数,判断如果i为0或者i为numRows-1,flag反值,继续叠加(叠加不一定是正叠加,可能是负叠加)

  3. 遍历字符串的动态数组

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

代码

 1/*
 2直接遍历,遍历的过程中输出添加到vector<string> str
 3*/
 4class Solution {
 5public:
 6    string convert(string s, int numRows) {
 7      //边界条件
 8      if(numRows==1) return s;
 9      int i=0;
10      bool flag=false;
11      string tmp;
12      vector<string> str(min(int(s.length()),numRows));//强制转换s.length()为int  
13      for(char c:s)//c为当前元素,遍历整个s
14      {
15          str[i]+=c;
16          if(i==0||i==numRows-1) flag=!flag;
17          i+=flag?1:-1;   
18      }
19      for(string ss:str)
20          tmp+=ss; 
21      return tmp;                   
22    }
23};

思路2:找规律

  1. 很明显可以查找到规律,第一行和最后一行的间距都是2*numRows-2
  2. 其他的行,都会出现两次辗转累加的过程,而两次累加和为2numRows-2,例如第i行,第二个数比第一个数多2numRows-2-2i,第三个数则比第二个数多2i
  3. 设置一个flag用来判断辗转

代码

 1/*
 2找规律
 3*/
 4class Solution {
 5public:
 6    string convert(string s, int numRows) {
 7      //临时变量,用于存放新数组
 8        string tmp;
 9        int i,j;
10        bool flag=true;//除第一行最后一行都会辗转相加
11      //判断边界条件
12       if(s.length() < numRows) return s;
13       else if(numRows == 1) return s;
14       else if(numRows == 2)//奇偶输出
15       {
16           for(i = 0;i < s.length();i += 2)
17           {
18               tmp.push_back(s[i]);
19           }
20           for(i = 1;i <s.length();i += 2)
21           {
22               tmp.push_back(s[i]);
23           }
24           return tmp;
25       }
26       else //一般情况
27       {
28           for( i=0;i<numRows;i++)
29           {
30               
31               if(i == 0)
32               {
33                   for(j=i;j<s.length();j+= numRows*2-2)
34                       tmp.push_back(s[j]);
35               }
36               else if(i == numRows-1)
37               {
38                   for(j=i;j<s.length();j+= numRows*2-2)
39                       tmp.push_back(s[j]);
40               }
41               else//其他的位置
42               {
43                   flag=true;//下一行自动为true
44                   tmp.push_back(s[i]);//第一列第一个数
45                   j=i;
46                   while(j<s.length())
47                   {
48                       if(flag)
49                       {
50                       flag=false;
51                      
52                           j+= numRows*2-2-2*i;
53                           if(j>=s.length()) break;
54                            tmp.push_back(s[j]);
55                              
56                       }
57                       if(!flag)
58                       {
59                       flag=true;
60                      
61                           j+= 2*i;
62                           if(j>=s.length()) break;
63                            tmp.push_back(s[j]);
64                         
65                       }
66                   }
67               }    
68           }
69           
70       }
71        return tmp;
72    }
73};

如果本文对宝宝打开思路有帮助,可以点个赞哦~

参考

[1]最忆是南山

[2]扁扁熊

[3]力扣官方