leetcode_6

7 篇文章 0 订阅
4 篇文章 0 订阅

@YangYang48

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. 遍历字符串的动态数组

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

代码

/*
直接遍历,遍历的过程中输出添加到vector<string> str
*/
class Solution {
public:
    string convert(string s, int numRows) {
      //边界条件
      if(numRows==1) return s;
      int i=0;
      bool flag=false;
      string tmp;
      vector<string> str(min(int(s.length()),numRows));//强制转换s.length()为int  
      for(char c:s)//c为当前元素,遍历整个s
      {
          str[i]+=c;
          if(i==0||i==numRows-1) flag=!flag;
          i+=flag?1:-1;   
      }
      for(string ss:str)
          tmp+=ss; 
      return tmp;                   
    }
};

思路2:找规律

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

代码

/*
找规律
*/
class Solution {
public:
    string convert(string s, int numRows) {
      //临时变量,用于存放新数组
        string tmp;
        int i,j;
        bool flag=true;//除第一行最后一行都会辗转相加
      //判断边界条件
       if(s.length() < numRows) return s;
       else if(numRows == 1) return s;
       else if(numRows == 2)//奇偶输出
       {
           for(i = 0;i < s.length();i += 2)
           {
               tmp.push_back(s[i]);
           }
           for(i = 1;i <s.length();i += 2)
           {
               tmp.push_back(s[i]);
           }
           return tmp;
       }
       else //一般情况
       {
           for( i=0;i<numRows;i++)
           {
               
               if(i == 0)
               {
                   for(j=i;j<s.length();j+= numRows*2-2)
                       tmp.push_back(s[j]);
               }
               else if(i == numRows-1)
               {
                   for(j=i;j<s.length();j+= numRows*2-2)
                       tmp.push_back(s[j]);
               }
               else//其他的位置
               {
                   flag=true;//下一行自动为true
                   tmp.push_back(s[i]);//第一列第一个数
                   j=i;
                   while(j<s.length())
                   {
                       if(flag)
                       {
                       flag=false;
                      
                           j+= numRows*2-2-2*i;
                           if(j>=s.length()) break;
                            tmp.push_back(s[j]);
                              
                       }
                       if(!flag)
                       {
                       flag=true;
                      
                           j+= 2*i;
                           if(j>=s.length()) break;
                            tmp.push_back(s[j]);
                         
                       }
                   }
               }    
           }
           
       }
        return tmp;
    }
};

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

参考

[1]最忆是南山
[2]扁扁熊
[3]力扣官方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值