乘风破浪:LeetCode真题_006_ZigZag Conversion
乘风破浪:LeetCode真题_006_ZigZag Conversion
一、前言
到这里我们对基本的问题有了一定的理解,其中字符串的操作一直是一个比较困难的问题,这一点我们需要认真对待,采用合理的方案去解决问题。下面我们就看看将字符串按照某种格式排列之后再按行输出的问题。
二、ZigZag Conversion
2.1 问题理解


2.2 分析以解决问题
看到这样的问题我们最直接的想法就是构造一个二维数组,初始化成某种字符,然后按照题目给定的规则进行填充,填充完成之后按行进行遍历,将结果拼凑起来输出出去。这种方法复杂度为O(n~2)。因此我们进行优化,采用StringBuilder这样的结构来直接进行存储,能够将时间复杂度缩小到O(n)。
下面是官方的解法:
 class Solution {
     public String convert(String s, int numRows) {
         if (numRows == 1) return s;
         List<StringBuilder> rows = new ArrayList<>();
         for (int i = 0; i < Math.min(numRows, s.length()); i++)
             rows.add(new StringBuilder());
         int curRow = 0;
         boolean goingDown = false;
         for (char c : s.toCharArray()) {
             rows.get(curRow).append(c);
             if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
             curRow += goingDown ? 1 : -1;
         }
         StringBuilder ret = new StringBuilder();
         for (StringBuilder row : rows) ret.append(row);
         return ret.toString();
     }
 }

我们的算法:
public class Solution {
    /**
     * 题目大意
     * 输入一个字符串和指定的行数,将字符以Z字型输出。
     *
     * 解题思路
     * 计算出字符的最大列数,根据列数和行数创建一个一维数组,再计算每个字符中一维数组中的位置,
     * 再对一维数组中的字符进行紧凑操作,返回结果。
     * </pre>
     *
     * @param s
     * @param nRows
     * @return
     */
    public String convert(String s, int nRows) {
        if (s == null || s.length() <= nRows || nRows == 1) {
            return s;
        }
        int index = s.length();
        int rowLength = 0; // 计算行的长度,包括最后换行字符
        int slash = nRows - 2; // 一个斜线除去首尾所占用的行数
        while (index > 0) {
            // 竖形的一列
            index -= nRows;
            rowLength++;
            // 斜着的列数
            for (int i = 0; i < slash && index > 0; i++) {
                rowLength++;
                index--;
            }
        }
        char[] result = new char[nRows * rowLength]; // 保存结果的数组,最后一列用于保存换行符
        for (int i = 0; i < result.length; i++) { // 初始化为空格
            result[i] = ' ';
        }
        int curColumn = 0; // 当前处理的行数
        index = 0;
        while (index < s.length()) {
            // 处理竖线
            for (int i = 0; i < nRows && index < s.length(); i++) {
                result[rowLength * i + curColumn] = s.charAt(index);
                index++;
            }
            curColumn++;
            // 处理斜线
            for (int i = nRows - 2; i > 0 && index < s.length(); i--) {
                result[rowLength * i + curColumn] = s.charAt(index);
                curColumn++;
                index++;
            }
        }
        // 对字符数组进行紧凑操作
        index = 0;
        while (index < s.length() && result[index] != ' ') { // 找第一个是空格的字符位置
            index++;
        }
        int next = index + 1;
        while (index < s.length()) {
            while (next < result.length && result[next] == ' ') { // 找不是空格的元素
                next++;
            }
            result[index] = result[next];
            index++;
            next++;
        }
        return new String(result, 0, index);
    }
}
这样的算法其实就是笨办法了,首先计算出虚拟的二维数组需要的空间大小,然后实际上(物理上)用一维数组来表示,并且初始化为空,之后将源字符串的字符按照规则填到虚拟的二维数组中,其实是一维数组,最后将一维数组中的空格去除掉就得到了想要的结果,显然是一个O(n~2)的算法,没有官方的好。

三、总结
通过这样的一个例子,我们可以发现往往我们的原始想法都是暴力法,按部就班的来,只要稍微的优化一下就能变成更好的方法,得到更优质的结果,写更少的代码。
乘风破浪:LeetCode真题_006_ZigZag Conversion的更多相关文章
- 乘风破浪:LeetCode真题_041_First Missing Positive
		乘风破浪:LeetCode真题_041_First Missing Positive 一.前言 这次的题目之所以说是难,其实还是在于对于某些空间和时间的限制. 二.First Missing Posi ... 
- 乘风破浪:LeetCode真题_040_Combination Sum II
		乘风破浪:LeetCode真题_040_Combination Sum II 一.前言 这次和上次的区别是元素不能重复使用了,这也简单,每一次去掉使用过的元素即可. 二.Combination Sum ... 
- 乘风破浪:LeetCode真题_039_Combination Sum
		乘风破浪:LeetCode真题_039_Combination Sum 一.前言 这一道题又是集合上面的问题,可以重复使用数字,来求得几个数之和等于目标. 二.Combination Sum ... 
- 乘风破浪:LeetCode真题_038_Count and Say
		乘风破浪:LeetCode真题_038_Count and Say 一.前言 这一道题目,很类似于小学的问题,但是如果硬是要将输入和结果产生数值上的联系就会产生混乱了,因此我们要打破思维定势. ... 
- 乘风破浪:LeetCode真题_037_Sudoku Solver
		乘风破浪:LeetCode真题_037_Sudoku Solver 一.前言 这次我们对于上次的模型做一个扩展并求解. 二.Sudoku Solver 2.1 问题 2.2 分析与解决 这道题 ... 
- 乘风破浪:LeetCode真题_036_Valid Sudoku
		乘风破浪:LeetCode真题_036_Valid Sudoku 一.前言 有的时候对于一些基础知识的掌握,对我们是至关重要的,比如ASCII重要字符的表示,比如一些基本类型的长度. 二.Valid ... 
- 乘风破浪:LeetCode真题_035_Search Insert Position
		乘风破浪:LeetCode真题_035_Search Insert Position 一.前言 这次的问题比较简单,也没有限制时间复杂度,但是要注意一些细节上的问题. 二.Search Insert ... 
- 乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array
		乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array 一.前言 这次我们还是要改造二分搜索,但是想法却 ... 
- 乘风破浪:LeetCode真题_033_Search in Rotated Sorted Array
		乘风破浪:LeetCode真题_033_Search in Rotated Sorted Array 一.前言 将传统的问题进行一些稍微的变形,这个时候我们可能无所适从了,因此还是实践出真知, ... 
随机推荐
- vim操作命令备忘
			vim操作命令备忘 查找/替换 :%s/keyword//gn //搜索匹配的关键词数量 :%s/keywords/target //替换关键词 待续…… 
- 去掉img标签周围的空白
			我们在页面布局的时候,明明已经去掉了所有标签的margin和padding,img标签周围依然会有空白,解决方法有以下几种: 1.给img标签设浮动: img{ float:left; } 2.将im ... 
- IOS Core Image之一
			项目中要实现高斯模糊的效果,今天看了下Core Image这块的内容, 主要包括CIImage.CIFilter.CIContext.CIDetector(检测).CIFeature(特征)等类. 今 ... 
- webstorm软件小技巧
			1.使用tab可以方便的生成代码片段 调出setting,搜索live template 在javascrpt 模板线面点击"+" 添加一个模板 fun 模板内容如下 functi ... 
- php常用的时间函数
			测试环境:php5.3.29 unix时间戳(从Unix 纪元(January 1 1970 00:00:00 GMT)到给定时间的秒数.).以下简称时间戳. 设置默认时区 date_default_ ... 
- js原型及原型链解析
			js原型.原型链 这几天闲了看了下js的原型,以下内容为个人理解,如有错误,尽请指正. 首先,明确一点:js中的对象分为普通对象和函数对象,一般我们自定义的可以被new的函数称作函数对象,另外js内置 ... 
- Asp.Net 之Jquery知识点运用
			1.先把要用的body内的代码写好. <div id="ulBox"> <h3>下面的Ulid为"ulList1"</h3> ... 
- GIT使用log命令显示中文乱码
			背静: 公司项目使用GIT进行代码同步. 问题: 之前代码提交后,有中文备注,但是在使用git log查看代码历史记录的时候发现显示乱码,如下: 后查询相关资料,现将解决办法总结如下: 1.运行Git ... 
- js  控制选中文字
			//脚本获取网页中选中文字 var word = document.selection.createRange().text; //获取选中文字所在的句子 var range = documen ... 
- vscode 实用的插件
			REST-Client api接口测试插件 在项目中新建以.http后缀名的文件即可. 右键使用 可以生产多种语言的请求代码块.可以说是非常舒服了. 使用代码块功能生成了node环境的http请求. ... 
