LeetCode6-Z字形变换

简介: LeetCode6-Z字形变换

题目



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

比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

L   C   I   
RE T O E S I I G
E   D   H   N


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

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


string convert(string s, int numRows);


示例



输入: s = “LEETCODEISHIRING”, numRows = 4

输出: “LDREOEIIECIHNTSG”

解释:

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


分析



方法一:


假如 s = “PAYPALISHIRING”, numRows = 4 (括号里的数字代表这个字符在该字符串的位置)



首先可以确定的是中间斜着的行数(也就是每两个竖列之间的间隔)是gap = numRows - 2 =2


观察可以发现:


第一行和最后一行都是每隔6位取一位 通过观察 ,可以通过(numRows-1)+gap+1得到 其实就是竖着的4个(因为下标从0开始计算,所以应该减一) 加上两个斜着的(gap) 再加上另一列上的1(语言表达能力不太好,希望大家可以看的懂。。。。。) 这样可以计算出首行和尾行的间隔,将这个间隔设为k1,k1 = 6


第二行是1,5,7,11,13 间隔是 +4 +2 +4 +2 … 这个可以两个看作一组,4就是 k2 = k1-i*2 = k1-2 (这里的i是指行数,从0开始计算) ,2可以看作 k1 - k2


第三行是2,4,8,10 间隔是 +2 +4 +2 +4 同样,2是k2 = k1 - i*2 = k1 -4 ,4位k1-k2


验证上面的规律:


s= “PAYPALISHIRING” , numRows = 3 (括号里的数字代表这个字符在该字符串的位置)



gap = numRows - 2 =1


第一行和最后一行都是每隔4位取一位 k1 = (numRows-1)+gap+1 = 3-1+1+1 = 4


第二行是1,3,5,7,9 每次位数增加2 i = 1, +2 +2 +2 +2… k2 = k1-i*2 = k1-2 = 4-2 = 2 后面就可以直接用 k1-k2 然后每次更新k2即可


如果不放心 ,可以另取一个numRows较大的字符串进行测试。


找到规律以后就可以直接编写代码,值得注意的是 这里会有一个边界条件,length == 0或length<=numRows或numRows==1都可以直接输出,不需要进行操作。


方法二:




方法三:

自己体会,这个代码效率是最高的!!!


代码



package com.leetcode.code;
import java.util.ArrayList;
import java.util.List;
/** 
* LeetCode6-Z字形变换 
* 
* 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
*
* 比如输入字符串为 "LEETCODEISHIRING" 行数为 4 时,排列如下: 
*
* 输入: s = "LEETCODEISHIRING", numRows = 4 
* 输出: "LDREOEIIECIHNTSG" 
* 解释: 
*
* L     D     R 
* E   O E   I I
* E C   I H   N
* T     S     G
* 
*/
public class LeetCode6 {  
  // 方法一   
  public static String convert(String s, int numRows) {   
    int length = s.length();   
    if(length == 0 || length <= numRows || numRows == 1) { 
      return s;     
    }      
    int gap = numRows - 2;   
    String ans = "";     
    int k1 = numRows -1 + gap + 1;    
    for (int i = 0; i < numRows; i++) {    
      int location = 0;     
      if (i==0 || i == numRows - 1) {           
        ans = ans + s.charAt(i);      
        location = i + k1;      
        while (location < length) {    
          ans = ans + s.charAt(location);  
          location = location + k1;      
        }            
      } else {     
        ans = ans + s.charAt(i);    
        int k2 = k1 - i * 2;    
        location  = location + k2 + i;  
        while (location < length) {  
          ans = ans + s.charAt(location);     
          k2 = k1 - k2;            
          location  = k2 + location;        
        }        
      }      
    } 
    return ans;   
  }
    // 方法二  
    public static String convert2(String s, int numRows) { 
      if (numRows < 2) {     
        return s;     
      }     
      List<StringBuilder> rows = new ArrayList<StringBuilder>();  
      for (int i = 0; i < numRows; i++) {    
        rows.add(new StringBuilder());     
      }     
      int i = 0, flag = -1;     
      for (char c : s.toCharArray()) {    
        rows.get(i).append(c);     
          if (i == 0 || i == numRows - 1) {   
            flag = - flag;           
          }          
          i += flag;   
        }       
        StringBuilder result = new StringBuilder();  
        for (StringBuilder row : rows) {   
          result.append(row);    
        }      
        return result.toString();  
    }
    // 方法三  
    public String convert3(String s, int numRows) {  
      if (numRows == 1) {  
         return s;     
      }    
      int step = (numRows - 1) << 1;   
      int len = s.length();      
      char[] ans = new char[len];     
      char[] chars = s.toCharArray(); 
      int index = -1;       
      for (int i = 0; i < numRows; i++) { 
        for (int j = i; j < len; j += step) {  
          ans[++index] = chars[j];       
          if (i != 0 && i != numRows - 1 && step - (i << 1) + j < len) {   
            ans[++index] = chars[step - (i << 1) + j];     
          }           
        }       
      }       
      return new String(ans);  
    }
    public static void main(String[] args) {  
    System.out.println(convert("LEETCODEISHIRING", 4));    
    System.out.println(convert2("LEETCODEISHIRING", 4));   
    System.out.println(convert2("LEETCODEISHIRING", 4)); 
    }
}


小结



  • 方法一是找规律的方法,也是大家普遍啊知道的方法,时间复杂度略高。
  • 方法二的妙处是用flag改变存储的方向,也是该方法的精髓所在。
  • 方法三是一个大佬写的代码,我就不做评价了哈哈哈。


性能上:方法一<方法二<方法三

相关文章
|
6月前
|
算法
LeetCode算法题---最长回文子串、N 字形变换(四)
LeetCode算法题---最长回文子串、N 字形变换(四)
41 0
|
1月前
|
算法 C++
Leetcode第六题(Z 字形变换)
这篇文章介绍了LeetCode第六题“Z字形变换”的解法,提供了C++的代码实现,其中使用了向量数组来模拟Z字形排列,并详细解释了算法的逻辑。
27 0
|
3月前
|
算法
LeetCode第6题N 字形变换
该文章介绍了 LeetCode 第 6 题 N 字形变换的解法,通过按列生成的方式,根据行数转换逻辑来构造字符串,主要注意控制行数的转换时机,从而实现 N 字形变换。
LeetCode第6题N 字形变换
|
3月前
|
Python
python实现:旋转矩阵转换为四元数
python实现:旋转矩阵转换为四元数
85 0
|
5月前
|
算法 索引 Perl
力扣经典150题第二十二题:Z 字形变换
力扣经典150题第二十二题:Z 字形变换
40 1
|
5月前
|
Perl
6.Z 字型变换
6.Z 字型变换
|
6月前
|
索引
leetcode代码记录(Z 字形变换
leetcode代码记录(Z 字形变换
44 1
|
6月前
leetcode-6:Z 字形变换
leetcode-6:Z 字形变换
44 0
|
6月前
|
C++
字形变换(C++)
字形变换(C++)
34 0