力扣第六题(Z字形变换)详解

 根据题目的意思,最初的想法是模拟,用一个二维数组模拟字符串在其中的排列,再用一个字符串按顺序接收二维数组中字符串,以此来得到答案。

方法一:具体的实现为首先判断字符串的长度,排除特殊情况。再用排列二维数组的周期t(t = r + r - 2 = 2 * r - 2,即先向二维数组的下方写入r个字符,再向右上方写入r - 2个字符),算出一个用多少列(用n / t可得要有多少个周期,再乘以(r - 1)行,可得矩阵的列数,这里用(n  + t - 1/ t)是为了求余 的时候可以向上取整。)具体的实现代码如下:

class Solution {
public:
    string convert(string s, int numRows) {
    int n = s.length(),r = numRows;
    if(r == 1 || r >= n) return s;//初始条件判断
    int t = 2 * r - 2;//记录字符排序的周期
    int c = (n + t - 1) / t * (r - 1);//字符排序的列数
    vector<string> mat(r,string(c,0));
    for(int i = 0,x = 0,y = 0;i < n;i++){
       mat[x][y] = s[i];//将字符串赋值给二维数组
       if(i % t < (r - 1){//将字符向下赋值
       ++x;
      }else//{将字符向右上赋值
       --x;
       ++y;
      }
   }
     string ans;
      for(auto &rt : mat){
         for(char row : rt){
            if(ch){
             ans += ch;//将二维数组中的值赋值给字符串
            }
           }
       }
       return ans;
    }
}; 

 二维数组模拟所消耗的时间和空间较大,可以进行进一步的优化。

方法二:对于知道最后位置和初始位置关系,可以直接构造出初始位置和最后关系的函数,然后可以直接得到最终结果。

前面几步和方法一一样,后面的在于不用把字符串在二维数组中模拟,而是直接跳着连接上所有字符。第一层循环是行的递增,逐步增加。第二层循环是对于列来说,列的增加是以周期t为准,以正Z字形方式累加得到最后的结果。

class Solution {
public:
    string convert(string s, int numRows) {
       int n = s.length(),r = numRows;
       if(r == 1 || r >= n){
           return s;
       }
       string ans;
       int t = 2 * r - 2;
       for(int i = 0;i < r;i++){
           for(int j = 0;j + i < n;j += t){
               ans += s[j + i];
               if(i > 0 && i < r - 1 && j + t - i < n){//右上角的字符
                   ans += s[j + t - i];
               }
           }
       }
       return ans;
    }
};

 该方法的时间和空间效率都有很大的提高,而且较为容易理解,很适合学习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值