LeetCode刷题笔记(六)Z字形变换

题目:

    将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数:

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

解法1:这是一种很笨的方法,一开始一位规律会很难找,所以就想到用这种方法先做出来再说,

class Solution {
    public String convert(String s, int numRows) {
        if(numRows==1){
            return s;
        }
        StringBuilder str = new StringBuilder();
        List<char[]> list = new ArrayList<>();   //存储整个的Z形的所有列
        int size = 0,len = s.length();
        for(int i = 0;i<len;i++){
            char[] chars = new char[numRows];    //存储每一列的数据
            int remainder = i%(numRows-1);       //计算余数,确定是否是整列
            for(int j = remainder==0?0:numRows-1-remainder;j<numRows-remainder;j++){   //如果是整列起点为0,否则为numRows-1-remainder
                chars[j] = s.charAt(size++);      //把列上的数据填到对应位置  
		if(size>=len){           //全部遍历完跳出循环
                       break;
                };
            }
            list.add(chars);             //把每一列的数据加入集合
            if(size>=len){
                    break;
            };
        }
        for(int j = 0;j<numRows;j++){         //遍历集合把为默认值的char排除拼接起来
            for(int i = 0,length = list.size();i<length;i++){
                char[] chars = list.get(i);
                if(chars[j]!='\u0000'){
                    str.append(chars[j]);
                }
            }
        }
        return str.toString();
    }
}

这里就是把每一列的数据都遍历出来,以char数组的结构存到以list上,然后再通过遍历把不是默认值的字符拼接起来,其实这里如果用二维数组可能效果会好一点,在第二遍历的时候空间复杂度会小一点;

时间复杂度:O(n)

空间复杂度:O(n^2)

解法2:

class Solution {
    public String convert(String s, int numRows) {
        int length = s.length();
        if(length<=1||numRows<=1){   //特殊参数情况处理
            return s;
        }
        StringBuilder str = new StringBuilder();
        
        for(int i = 0;i<numRows;i++){        //一行一行遍历出字符
            int num = i;
            while(num<length){
                str.append(s.charAt(num));         
                if(i!=0&&i!=numRows-1&&num+2*(numRows-1-i)<length){   //如果不是第一行和最后一行,把单独的一个字符拼接
                    str.append(s.charAt(num+2*(numRows-1-i)));
                }
                num += 2*(numRows-1);           //一个循环的等差
            }
        }
        return str.toString();  
    } 
}

这个方法直接遍历拼接字符串,因为我们可以找到对应的规律,先不考虑中间空缺的列,每一行对应的数对应的等差为2*(numRows-1);接下来考虑特殊情况,即不在第一行和最后一行的时候,把多余的一个字符加入进来,这里也可以发现规律,如果行数为num,则两个的差值为2*(numRows-1-num);所有直接遍历拼接出字符串,比起第一种解法少了求出每一列的计算。而且空间复杂度也小很多。提交的数据第一个时间为89ms,第二种解法为39ms;

时间复杂度:O(n);

空间复杂度:O(n)



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值