Leetcode-6、z字变换

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

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/zigzag-conversion 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、题解:
(1)方法1:按行排序:

使用 min(numRows,len(s))个列表来表示 Z 字形图案中的非空行。
从左到右迭代 s,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。
只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。
在这里插入图片描述

class Solution {
    public String convert(String s, int numRows) {//("PAYPALISHIRING",3)

        if (numRows == 1) return s;

        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < Math.min(numRows, s.length()); i++)//0 1 2 
            rows.add(new StringBuilder());// 结果为[ , , ]

        int curRow = 0;//flag
        boolean goingDown = false;

        for (char c : s.toCharArray()) {//P A Y P A L I S H I R I N G
        //增强for循环
        //toCharArray() 方法将字符串转换为字符数组
            rows.get(curRow).append(c);//调用List型的rows的get方法得到Stringbuilder型的字符,再用append方法,结果为:[P, , ]
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;//true
            // if (curRow == 0 || curRow == numRows - 1){
            // goingDown = !goingDown;
            //}
            curRow += goingDown ? 1 : -1;//goingDown为true则+1,为false则-1
        }
//最终得到结果[P,A,Y]
//            [ ,P, ]
//            [A,L,I]
//            ...
        StringBuilder res = new StringBuilder();//创建res对象
        for (StringBuilder row : rows) res.append(row);//rows[1]={P,A,H,N} ...
        return res.toString();
    }
}

复杂度分析:
时间复杂度:O(n),其中n==len(s)
空间复杂度:O(n)
作者:LeetCode 链接:https://leetcode-cn.com/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

知识点:
①List:

/**1、Collection接口:单列集合(单列数据),用来存储一个一个的对象
 *        >List:元素有序、可重复的集合。-->”动态“数组
 *              >ArrayList、LinkedList、Vector
 * List接口概述:
 *   鉴于Java中数组用来存储数据的局限性,通常使用List来替代数组,“动态数组”
 *   List集合类中元素有序、可重复,集合中的每个元素都有其对应的顺序索引
 *   List荣放弃中的元素都对用一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
 *   JDK API中List接口的实现类常有的有:
 *   --ArrayList:作为List接口的主要实现类。线程不安全的、效率高;底层使用Object[] elementData存储。
 *   --LinkedList:对于频繁的插入和删除操作,使用此类效率比ArrayList高;底层使用双向链表存储。
 *   --Vector:作为List接口的老实现类。线程安全,效率不高。底层使用Object[] elementData存储。
 * 
* List接口中的常用方法:
 * add(int index,Object ele):在index位置插入ele元素
 * addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来
 * get(int index):获取指定index位置的元素
 * indexOf(Object obj):返回obj在当前集合中首次出现的位置
 * LastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
 * remove(int index):移除指定index位置的元素,并返回此元素
 * set(int index,Object ele):设置指定index位置的元素为ele
 * subList(int fromIndex,int toIndex):返回从fromIndex到toIndex的子集合
 *
  */

②StringBuilder:

/**
常用类:
String、StringBuffer、StringBuilder三者的异同?
String:不可变的字符序列,底层使用char[]存储
StringBuffer:可变的字符序列,线程安全的,效率低;底层使用char[]存储
StringBuilder:可变的字符序列,JDK5.0新增的。线程不安全的,效率高;底层使用char[]存储
源码分析:
String str =new String();               //底层结构 char[] value=new char[0];
String str1=new String("abc");          //char[] value=new char[]{'a','b','c'};
StringBuffer sb1=new StringBuffer();    //char[] value=new char[16];底层创建了一个长度时16的数组。
System.out.println(sb1.;length());      //
sb1.append('a');                        //value[0]='a';
sb1.append('b');                        //value[1]='b';
StringBuffer sb2=new StringBuffer("abc");//char[] value=new char["abc".length()+16]
//问题1.System.out.println(sb2.length());//3
//问题2.扩容问题:如果要添加的数据底层数组盛不下啦,那就要扩容底层的数组。
       默认情况下,扩容我i原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。
  指导意义:开发中建议大家使用StringBuffer(int capacity)
 ·
* StringBuffer类的常用方法
     * StringBuffer append():
     * StringBuffer delete():
     * StringBuffer replace():
     * StringBuffer insert():
     * StringBuffer reverse():
     * public int indexOf(String str)
     * public String substring(int start,int end):返回一个从start开始到索引结束的左闭右开区间的额子字符串。
     * public int length()
     * public char charAt(int n)
     * public void setCharAt(int n,char ch)
  */

(1)方法2:按行访问:

class Solution {
    public String convert(String s, int numRows) {

        if (numRows == 1) return s;

        StringBuilder ret = new StringBuilder();
        int n = s.length();
        int cycleLen = 2 * numRows - 2;

        for (int i = 0; i < numRows; i++) {
            for (int j = 0; j + i < n; j += cycleLen) {
                ret.append(s.charAt(j + i));
                if (i != 0 && i != numRows - 1 && j + cycleLen - i < n)
                    ret.append(s.charAt(j + cycleLen - i));
            }
        }
        return ret.toString();
    }
}
复杂度分析

作者:LeetCode
链接:https://leetcode-cn.com/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间复杂度:O(n),其中 n==len(s)。每个索引被访问一次。
空间复杂度:O(n)。对于 C++ 实现,如果返回字符串不被视为额外空间,则复杂度为 O(1)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值