• LeetCode No6 Z字形变换


    题目

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

    比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

    P   A   H   N
    A P L S I I G
    Y   I   R
    

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

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

    string convert(string s, int numRows);

    示例 1:

    输入:s = "PAYPALISHIRING", numRows = 3
    输出:"PAHNAPLSIIGYIR"

    示例 2:

    输入:s = "PAYPALISHIRING", numRows = 4
    输出:"PINALSIGYAHRPI"
    解释:

    P     I    N
    A   L S  I G
    Y A   H R
    P     I
    

    示例 3:

    输入:s = "A", numRows = 1
    输出:"A"

    提示:

    1 <= s.length <= 1000
    s 由英文字母(小写和大写)、',' 和 '.' 组成
    1 <= numRows <= 1000

    思路

    模拟

    题目的操作并不复杂,可以直接按照题目意思直接模拟,将字符串转化成一个矩阵,然后再遍历矩阵即可得到最后的字符串。但是这种方式提交很容易超时,而且构建出的矩阵有很大部分都是浪费掉了。

    直接构造

    相对于模拟得到最后的矩阵,其实我们并不在意最后的矩阵到底是什么样子的,我们如果能够明白构建矩阵的规律,那么就可以直接按照规律去取数,不需要真正的构建矩阵,那么我们先研究下当行数numRows 小于4的时候分别是什么样子。
    numRows 为1:

    0 1 2 3 4 5 6 7 ... n
    

    numRows 为2:

    0 2 4 6 ... n-1
    1 3 5 7 ... n
    

    numRows 为3

    0   4   8     12  
    1 3 5 7 9  11 
    2   6   10 
    

    numRows 为4

    0    6      12      18
    1  5 7   11 13    17
    2 4  8 10   14  16
    3    9      15
    

    可以看到其实所有的变幻操作都是在循环的打钩 [ √ ],以numRows=4为例:

    0    | 6      | 12       |18   
    1  5 | 7   11 | 13    17 |19     23
    2 4  | 8 10   | 14  16   |20  22
    3    | 9      | 15       |21
    

    而每次打钩 [ √ ]所需要的字符个数t也是和numRows有关:

    当numRows=1时:t=1
    当numRows=2时:t=2
    当numRows=3时:t=4
    当numRows=4时:t=6
    ...
    当numRows=n时:t=2*n-2
    

    那这样我们就可以推断出numRows=n的时候,所循环的钩 [ √ ]应该如下[t=2*n-2]:

    0
    1               t-1
    2             t-2
    3           t-3
    4         t-4
    5       t-5
    6     t-6
    ......
    n-1
    

    那这个时候我们只需要用for循环按行去读取对应的字符,也就不需要在代码中构建出最后的矩阵了。

    AC代码

    模拟

    点击查看代码
    class Solution {
        public String convert(String s, int numRows) {
            if( numRows == 1 ) {
                return s;
            }
            char[] chars = s.toCharArray();
            int len = chars.length;
            char[][] charss = new char[numRows][len];
            int i = 0;
            int j = 0;
            int index = 0;
            while( index<len ) {
                if( i==0 ) {
                    if( j!=0 ) {
                        // 第一次的时候是以第一行为起点,其他循环次数的时候是一第二行为起点
                        i ++;
                    }
                    while( i < numRows && index<len ) {
                        charss[i][j] = chars[index];
                        i ++;
                        index ++;
                    }
                    i --;
                }
                if( i == numRows-1 ) {
                    while(i>0 && index<len ) {
                        i --;
                        j ++;
                        charss[i][j] = chars[index];
                        index ++;
                    }
                }
            }
            StringBuffer sb = new StringBuffer();
            for(i=0; i<numRows; i++) {
                System.out.println();
                for(j=0; j<len; j++) {
                    System.out.print(charss[i][j] + " ");
                    if(Character.isLetter(charss[i][j]) || charss[i][j]=='.' || charss[i][j]==',') {
                        sb.append(charss[i][j]);
                    }
                }
            }
            return sb.toString();
        }
    }
    

    直接构造

    点击查看代码
    class Solution {
        public String convert(String s, int numRows) {
            int len = s.length();
            if (numRows == 1 || numRows >= len) {
                return s;
            }
            char[] chars = s.toCharArray();
            StringBuffer sb = new StringBuffer();
            int t = numRows * 2 - 2;
            for (int i = 0; i < numRows; ++i) {
                // 循环打√
                for (int j = 0; j + i < len; j += t) {
                    sb.append(chars[j+i]);
                    // 找一次循环的第二个值,同时第一行和最后一行只有一个值,不需要找
                    if (0 < i && i < numRows - 1 && j + t - i < len) {
                        sb.append(chars[j + t - i]);
                    }
                }
            }
            return sb.toString();
        }
    }
    
  • 相关阅读:
    Node 核心模块HTTP模块
    Node 的 模块 及fs 模块的使用
    Node 简介和环境安装
    RBAC权限管理模型:基本模型及角色模型解析及举例
    JS中Ajax的同步和异步
    tp5.1 获取json对象的json内容
    JavaScript 判断对象中是否有某属性
    php 函数使用可变数量的参数
    ThinkPHP5.1关于查询器查询条件为[NOT] NULL时的写法
    js中const,var,let区别
  • 原文地址:https://www.cnblogs.com/Asimple/p/16132170.html
Copyright © 2020-2023  润新知