【LeetCode 006】Zigzag Conversion.md

题目

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

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

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:

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

Contributor

翻译

把字符串上下上下走之字形状,然后按行输出,比如包含数字0~22的字符串, 给定行数为5

题解

解法一

这道题就是看坐标的变化。并且需要分块处理。

n=2时,字符串坐标变成zigzag的走法就是:

0 2 4 6

1 3 5 7

n=3时的走法是:

0 4 8

1 3 5 7 9

2 6 10

n=4时的走法是:

0 6 12

1 5 7 11 13

2 4 8 10 14

3 9 15

可以发现规律,加粗倾斜的长度永远是 2n-2 (想法是你试想把所有这些行压缩成两列,两边手挤一下,第二列永远的第一行和最后一行少字)。

利用这个规律,可以按行填字,第一行和最后一行,就是按照2n-2的顺序一点点加的。

其他行除了上面那个填字规则,就是还要处理斜着那条线的字,可以发现那条线的字的位置永远是当前列j+(2n-2)-2i(i是行的index)。

按照上面的规律就可以写出代码了。

public static String convert(String s, int numRows) {
    if(s == null || s.length()==0 || numRows <=0) {
        return "";
    }
    if(numRows == 1) {
        return s;
    }

    StringBuilder res = new StringBuilder();
    int size = 2*numRows-2;
    for(int i=0;i<numRows;i++){
        for(int j=i;j<s.length();j+=size){
            res.append(s.charAt(j));
            if(i != 0 && i != numRows - 1){
                int temp = j+size-2*i;
                if(temp<s.length()) {
                    res.append(s.charAt(temp));
                }
            }
        }
    }
    return res.toString();
}

解法二

首先,题目中给出了几个比较关键的东西:

(1)给定了行数;

(2)Z形的这种字符串应该分两种情况处理;第一种是“垂直”部分,即题目例子中第一列“PAY”,第三列“ALT”这种;第二种就是”斜线“的,如”YPA“和”ISH“这种类型的。

​ 根据以上思路,可以得到如下代码:

public String convert2(String s, int numRows) {
    char[] c = s.toCharArray();
    int len = c.length;
    StringBuffer[] sb = new StringBuffer[numRows];
    for (int i = 0; i < sb.length; i++) {
        sb[i] = new StringBuffer();
    }
    int i = 0;
    while (i < len) {
        for (int idx = 0; idx < numRows && i < len; idx++) {
            sb[idx].append(c[i++]);
        }
        for (int idx = numRows-2; idx >= 1 && i < len; idx--) {
            sb[idx].append(c[i++]);
        }
    }
    for (int idx = 1; idx < sb.length; idx++) {
        sb[0].append(sb[idx]);
    }
    return sb[0].toString();
}

看一下while循环中的for循环,第一个for循环处理的是”垂直“部分,非常容易理解;第二个就稍微难一点,”斜线“部分的第一个和最后一个元素我们都是不需要在这里处理的,应该直接用”垂直“部分处理第一个元素和最后一个元素。那剩下的部分就是第二个元素和倒数第二个元素以及他们之中的部分,这个范围是什么?这个范围就是大于等于1小于等于行数减2(因为行数减1是最后一个元素)。

​ while循环结束,将分散的stringbuffer类型的数组整合成一个stringbuffer对象,然后直接使用toString转化成String类型返回即可。

解法-python

给出一个字符串,按照之字形(Zigzag)排列成矩形,将矩阵每一行连接起来构成一个字符串。

img

将矩阵压缩得到:

img

#-*-coding:utf-8-*-
class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1:
            return s
        zigzag = ['' for i in range(numRows)]  # 初始化zigzag为['','','']
        row = 0                                # 当前的列数
        step = 1                               # 步数:控制数据的输入
        for c in s:
            if row == 0:
                step = 1
            if row == numRows - 1:
                step = -1
            zigzag[row] += c
            row += step
        return ''.join(zigzag)

Github地址:https://github.com/Bylant/LeetCode

CSDN地址:https://blog.csdn.net/ZBylant
微信公众号 在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值