[LeetCode 6] ZigZag Conversion

本文探讨了将字符串以Z字形方式写入指定行数的复杂问题,并提供了两种有效的解决方案。通过分析“PAYPALISHIRING”示例,详细解释了如何按行读取Z字形排列的字符串,包括关键的编程逻辑和潜在的陷阱。


[Problem Link]

Description

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

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

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

Solution 1

class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        int x = 2*numRows - 2;
        int length = s.length();
        string ans = "";
        for (int i = 0; i < numRows; i++) {
            int count = 0;
            while(1) {
                int first = count*x - i;
                int second = count*x + i;
                
                if (first < length && first >= 0) {
                    ans = ans + s[first];
                } else if (first >= 0) {
                	break;
                    //一开始没有考虑到小于0的情况导致会尝试s[-1],本地跑不会报错,正确输出。而在leetcode上面就是wrong answer,leetcode会自动停止并不报错。
                } 
                if ((second) < length && i != 0 && i != numRows-1) {
                    ans = ans + s[second];
                }
                count += 1;
            }
        }
        //cout << ans;
        return ans;
    }
};

不考虑到first小于0时,在leetcode上run会出现下面这种奇怪的情况。明明是输出ans后马上return ans,输出的值和return的值却不一样。初步考虑的原因是leetcode编译的原因。
在这里插入图片描述

Solution 2

class Solution {
public:
    string convert(string s, int numRows) {
        //if (numRows == 1) return s;
        int x = 2*numRows - 2;
        int length = s.length();
        string ans = "";
        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j + i < length; j += x) {
                  ans += s[i+j]; 
                if (i != 0 && i != numRows - 1 && (j+x-i) < length) {
                     ans += s[j+x-i];
                 }
            }
            //cout << ans << ';';
        }
        return ans;
    }
};

Summary

  • 上面两种解法思路是一致的,只是第二种可读性更强,这道题要点就是找到规律,第一行出现的值的下标周期为 2 ∗ ( n − 1 ) 2*(n-1) 2(n1)。需要注意的是当n为1时,周期为0,就一直再第一个数值处循环,所以需要将n=1的情况单独处理。
  • 需要注意的是,string.length()返回的是无符号数,所以当负数与其进行比较时,会出现-1>string.length()这样的情况,因为计算机在遇到有符号数与无符号数进行运算时,会默认将有符号数当成无符号数处理,这点需要注意!
  • solution2中要先考虑竖排的数再考虑它右边是否存在斜排的数,一开始没想清楚,先考虑竖排数再考虑它左边是否存在斜排的数,导致最后一部分的数会漏掉,因为竖排数不存在直接略过了左边的斜排数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值