LeetCode

题目

URL:https://leetcode.com/problems/zigzag-conversion

解法

一、程序员

对于一个程序员来说,肯定是想模拟 ZigZag 的数组,再根据 ZigZag 的位置一行一行的输出。

ZigZag 模拟很简单,首先得出行数和列数,之后模拟 ZigZag 方式:先向下,后对角,都是遇到边界停下。

    public String convert(String s, int numRows) {
        if (numRows == 1) return s;

        int step = 2 * numRows - 2;
        int columnRows = (s.length() / step + 1) * (step / 2);
        char[][] c = new char[numRows][columnRows];

        int count = 0, i = 0, j = 0;
        boolean isDown = true;
        while (count < s.length()) {
            c[i][j] = s.charAt(count);
            count++;

            if (i == numRows - 1) {
                isDown = false;
            } else if (i == 0) {
                isDown = true;
            }

            if (isDown) {
                i++;
            } else {
                i--;
                j++;
            }
        }

        StringBuilder result = new StringBuilder();
        for (int row = 0; row < c.length; row++) {
            for (int col = 0; col < c[0].length; col++) {
                if (c[row][col] != 'u0000') result.append(c[row][col]);
            }
        }
        return result.toString();
    }

程序员,时间复杂度O(n2),运行时间约为 90 ms

二、数学家

必然有规律可以输出。

首先观察分组,每组数量是 2 * numRows - 2,对应的是一个纵列和对角列(当然不包括下一个纵列的头)。

其次观察分对,在分组中可以发现,第一个元素没有配对;第二个元素和倒数第一个元素配对;第三个元素和倒数第二个元素配对;······;中间有个元素,即 numRows -1 行的元素,是没有配对的,直接输出。

上面的思想完成之后,就可以具体实现:

  1. 输出第一列;
  2. 确定每个分组中每个分对的起始下标,输出分对元素;
  3. 输出最后一列。
    public String convert(String s, int numRows) {
        if (numRows == 1) return s;

        int step = 2 * numRows - 2;
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < s.length(); i += step) {
            result.append(s.charAt(i));
        }
        for (int line = 1; line < numRows - 1; line++) {
            for (int i = line; i < s.length(); i = i + step) {
                result.append(s.charAt(i));
                if (i + (numRows - line - 1) * 2 < s.length()) {
                    result.append(s.charAt(i + (numRows - line - 1) * 2));
                }
            }
        }
        for (int i = numRows - 1; i < s.length(); i += step) {
            result.append(s.charAt(i));
        }

        return result.toString();
    }

数学家,时间复杂度O(n2),运行时间约为 40 ms

总结

程序员会数学真的是要上天。程序员应该学好数学,数学是计算机的基础。利用数学相关知识,可以优化程序性能。

原文地址:https://www.cnblogs.com/Piers/p/7153001.html