LeetCode之(6)最长回文子串(Longest Palindromic Substring)

0006.最长回文子串(Longest Palindromic Substring)

题目描述

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

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

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

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

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

string convert(string s, int numRows);

示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"

示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:

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

题目分析

本题主要是寻找转变前后,字符串下标之间的关系,当然也可以真的生成一个Z字形排列的二维数组,但是没必要。

把整个字符串分成多个block,类似于一个V,如示例2中,则把LEETCO作为一个block,不足一个block的按照一个来看,那么就有len(s)/block_size个block,block_size与numRows有关,即block_size=2*numRows-2。可以看出,按照这样划分后,每个block的第一行和最后一行只有一个元素,其余行都有最多两个元素。每个block的元素下标是确定的,第i个(i=0,1,…)block的第一个字符的下标为i*block_size。

将字符串分块并确定下标后,就可以一层层的来输出字符串了。

需要特殊处理的是空串以及numRows=1的情况,直接返回原字符串即可。

代码实现

C++

/*
 * @lc app=leetcode.cn id=6 lang=cpp
 *
 * [6] Z 字形变换
 */

// @lc code=start
class Solution {
public:
    string convert(string s, int numRows) {
        if(s.size() == 0 || numRows == 1){
            return s;
        }

        string ans = "";
        string tmp = "";
        int block_size = 2 * numRows - 2;
        int block = (s.size() + block_size - 1) / block_size;

        for(int i = 0; i < block; i++){
            ans += s[i*block_size];
            int index = i*block_size + numRows - 1;
            if(index < s.size()){
                tmp += s[index];
            }
        }

        for(int i = 1; i < numRows - 1; i++){
            for(int j = 0; j < block; j++){
                int index1 = j*block_size + i;
                int index2 = (j+1)*block_size - i;
                if(index1 < s.size()){
                    ans += s[index1];
                }
                if(index2 < s.size()){
                    ans += s[index2];
                }
            }
        }

        ans += tmp;
        return ans;

    }
};
// @lc code=end

Java

/*
 * @lc app=leetcode.cn id=6 lang=java
 *
 * [6] Z 字形变换
 */

// @lc code=start
class Solution {
    public String convert(String s, int numRows) {
        if(s.length() == 0 || numRows == 1){
            return s;
        }

        String ans = "";
        String tmp = "";
        int block_size = 2 * numRows - 2;
        int block = (s.length() + block_size - 1) / block_size;

        for(int i = 0; i < block; i++){
            ans += s.charAt(i*block_size);
            int index = i*block_size + numRows - 1;
            if(index < s.length()){
                tmp += s.charAt(index);
            }
        }

        for(int i = 1; i < numRows - 1; i++){
            for(int j = 0; j < block; j++){
                int index1 = j*block_size + i;
                int index2 = (j+1)*block_size - i;
                if(index1 < s.length()){
                    ans += s.charAt(index1);
                }
                if(index2 < s.length()){
                    ans += s.charAt(index2);
                }
            }
        }

        ans += tmp;
        return ans;
    }
}
// @lc code=end

Python

#
# @lc app=leetcode.cn id=6 lang=python3
#
# [6] Z 字形变换
#

# @lc code=start
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if(len(s) == 0 or numRows == 1):
            return s
        
        ans = ""
        tmp = ""
        block_size = 2 * numRows - 2
        block = (len(s) + block_size - 1) // block_size

        for i in range(block):
            ans += s[i*block_size]
            index = i*block_size + numRows - 1
            if(index < len(s)):
                tmp += s[index]

        for i in range(1,numRows-1):
            for j in range(block):
                index1 = j*block_size + i
                index2 = (j+1)*block_size - i
                if(index1 < len(s)):
                    ans += s[index1]
                
                if(index2 < len(s)):
                    ans += s[index2]
        
        ans += tmp
        return ans 
            
# @lc code=end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值