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改变存储的方向,也是该方法的精髓所在。
  • 方法三是一个大佬写的代码,我就不做评价了哈哈哈。


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

相关文章
|
数据采集 算法 JavaScript
彩票中奖率的真相:用 JavaScript 看透彩票背后的随机算法(上)
原本这篇文章是打算叫「假如我是彩票系统开发者」,但细想一下,如果在文章中引用太多的 JavaScript 的话,反而不是那么纯粹,毕竟也只是我的一厢情愿,彩票开发也不全如本文所讲,有所误导的话便也是得不偿失了。
|
安全 Java 关系型数据库
医院门诊管理系统的设计与实现
医院门诊管理系统的设计与实现
231 1
|
11月前
|
编解码 缓存 算法
视频帧里的I帧、P帧、B帧是什么?
I帧、P帧、B帧是视频编码中的基本概念。I帧是帧内编码帧,无需参考其他帧即可解码;P帧是前向预测编码帧,基于前一帧解码;B帧是双向预测编码帧,基于前后帧解码。IDR帧是一种特殊的I帧,用于即时解码刷新,防止错误传播。GOP(Group of Pictures)是一组连续的画面,第一个帧为I帧,gop_size设置越大,画质越好,但解码延迟增加。OpenGOP允许GOP间的帧依赖,而ClosedGOP则不允许。DTS(解码时间戳)和PTS(显示时间戳)分别用于解码和显示时间控制。
|
JSON Java fastjson
简单实现_实体类与Json字符串互相转换
简单实现_实体类与Json字符串互相转换
326 1
|
12月前
|
Java 编译器 Android开发
java作业的提交规范与要求
java作业的提交规范与要求
148 0
|
人工智能 安全 算法
5G 网络中的加密:守护你的数据安全
5G 网络中的加密:守护你的数据安全
949 0
|
供应链 小程序 Java
基于Java超市库存管理系统设计和实现(源码+LW+调试文档+讲解等)
基于Java超市库存管理系统设计和实现(源码+LW+调试文档+讲解等)
|
存储 关系型数据库 MySQL
如何处理爬取到的数据,例如存储到数据库或文件中?
处理爬取的数据,可存储为txt、csv(适合表格数据)或json(适合结构化数据)文件。若需存储大量数据并执行复杂查询,可选择关系型(如MySQL)或非关系型(如MongoDB)数据库。以MySQL为例,需安装数据库和Python的pymysql库,创建数据库和表,然后编写Python代码进行数据操作。选择存储方式应考虑数据类型、数量及后续处理需求。
255 1
qt-两个界面传值交互
qt-两个界面传值交互
202 0
软件测试|Linux基础教程:cp命令详解,复制文件或目录
软件测试|Linux基础教程:cp命令详解,复制文件或目录