题目

标题和出处

标题:竖直打印单词

出处:1324. 竖直打印单词

难度

5 级

题目描述

要求

给你一个字符串 字符串题目:竖直打印单词 - 图1。请你按照单词在 字符串题目:竖直打印单词 - 图2 中的出现顺序将它们全部竖直返回。

单词应该以字符串列表的形式返回,必要时用空格补位,但输出尾部的空格需要删除(不允许尾随空格)。

每个单词只能放在一列上,每一列中也只能有一个单词。

示例

示例 1:

输入:字符串题目:竖直打印单词 - 图3
输出:字符串题目:竖直打印单词 - 图4
解释:每个单词都应该竖直打印。
字符串题目:竖直打印单词 - 图5
字符串题目:竖直打印单词 - 图6
字符串题目:竖直打印单词 - 图7

示例 2:

输入:字符串题目:竖直打印单词 - 图8
输出:字符串题目:竖直打印单词 - 图9
解释:题目允许使用空格补位,但不允许输出末尾出现空格。
字符串题目:竖直打印单词 - 图10
字符串题目:竖直打印单词 - 图11
字符串题目:竖直打印单词 - 图12

示例 3:

输入:字符串题目:竖直打印单词 - 图13
输出:字符串题目:竖直打印单词 - 图14

数据范围

  • 字符串题目:竖直打印单词 - 图15
  • 字符串题目:竖直打印单词 - 图16 仅含大写英文字母
  • 题目数据保证两个单词之间只有一个空格

解法

思路和算法

由于题目要求竖直打印单词,因此首先需要得到每个单词。在 Java 中,字符串题目:竖直打印单词 - 图17 类型有 字符串题目:竖直打印单词 - 图18 方法,将字符串根据指定的分隔符分隔成字符串数组。由于这道题中的两个单词之间只有一个空格,因此按照空格分隔字符串 字符串题目:竖直打印单词 - 图19 得到的字符串数组即为单词数组。

竖直打印单词,得到的字符串列表的列数等于单词数量,行数等于最大单词长度,因此需要遍历单词数组,得到最大单词长度,然后创建 字符串题目:竖直打印单词 - 图20 类型的数组 字符串题目:竖直打印单词 - 图21,数组长度为最大单词长度,用于存储竖直打印单词的结果。

得到最大单词长度和创建 字符串题目:竖直打印单词 - 图22 类型的数组 字符串题目:竖直打印单词 - 图23 之后,第二次遍历单词数组,对于每个单词,进行如下操作:

  1. 从左到右遍历该单词,从上到下遍历数组 字符串题目:竖直打印单词 - 图24,将该单词的每个字母依次拼接到数组 字符串题目:竖直打印单词 - 图25 的每一行;
  2. 如果该单词的长度小于最大单词长度,则对于数组 字符串题目:竖直打印单词 - 图26 中的剩余行,每行拼接一个空格。

遍历结束之后,数组 字符串题目:竖直打印单词 - 图27 存储了竖直打印单词的结果,此时每一行的尾部可能有空格,由于题目要求输出尾部的空格需要删除,因此还需要删除数组 字符串题目:竖直打印单词 - 图28 每一行尾部的空格。

删除尾部空格的直观的做法是对数组 字符串题目:竖直打印单词 - 图29 的每一行反向遍历,将该行末尾的空格删除。注意到最后一列有字母的行不可能有尾部的空格,而最后一列对应单词数组的最后一个单词,因此最后一列有字母的行数即为最后一个单词的长度,在删除尾部空格时可以跳过最后一列有字母的行。

例如,字符串题目:竖直打印单词 - 图30,数组 字符串题目:竖直打印单词 - 图31字符串题目:竖直打印单词 - 图32 行,最后一个单词 字符串题目:竖直打印单词 - 图33 长度为 字符串题目:竖直打印单词 - 图34,因此数组 字符串题目:竖直打印单词 - 图35 的前 字符串题目:竖直打印单词 - 图36 行没有尾部的空格,只要对后 字符串题目:竖直打印单词 - 图37 行删除尾部的空格。如下图所示,红色的位置表示需要删除的尾部的空格。

52_1.png

删除尾部空格之后,将数组 字符串题目:竖直打印单词 - 图39 的每一行添加到结果列表即可。

代码

  1. class Solution {
  2. public List<String> printVertically(String s) {
  3. String[] array = s.split(" ");
  4. int maxLength = 0;
  5. for (String word : array) {
  6. maxLength = Math.max(maxLength, word.length());
  7. }
  8. StringBuffer[] sb = new StringBuffer[maxLength];
  9. for (int i = 0; i < maxLength; i++) {
  10. sb[i] = new StringBuffer();
  11. }
  12. for (String word : array) {
  13. int length = word.length();
  14. for (int i = 0; i < length; i++) {
  15. sb[i].append(word.charAt(i));
  16. }
  17. for (int i = length; i < maxLength; i++) {
  18. sb[i].append(' ');
  19. }
  20. }
  21. int lastLength = array[array.length - 1].length();
  22. for (int i = maxLength - 1; i >= lastLength; i--) {
  23. int index = sb[i].length() - 1;
  24. while (index >= 0 && sb[i].charAt(index) == ' ') {
  25. sb[i].deleteCharAt(index);
  26. index--;
  27. }
  28. }
  29. List<String> list = new ArrayList<String>();
  30. for (int i = 0; i < maxLength; i++) {
  31. list.add(sb[i].toString());
  32. }
  33. return list;
  34. }
  35. }

复杂度分析

  • 时间复杂度:字符串题目:竖直打印单词 - 图40#card=math&code=O%28nl%29&id=qyH0B),其中 字符串题目:竖直打印单词 - 图41 是字符串 字符串题目:竖直打印单词 - 图42 的单词数,字符串题目:竖直打印单词 - 图43 是字符串 字符串题目:竖直打印单词 - 图44 的最大单词长度。
    • 需要遍历字符串数组两次,时间复杂度是 字符串题目:竖直打印单词 - 图45#card=math&code=O%28n%29&id=NqVCD);
    • 拼接数组 字符串题目:竖直打印单词 - 图46 的时间复杂度是 字符串题目:竖直打印单词 - 图47#card=math&code=O%28nl%29&id=GnBGE);
    • 将数组 字符串题目:竖直打印单词 - 图48 的每一行添加到结果列表的时间复杂度是 字符串题目:竖直打印单词 - 图49#card=math&code=O%28nl%29&id=jvsfQ)。
  • 空间复杂度:字符串题目:竖直打印单词 - 图50#card=math&code=O%28nl%29&id=wAM39),其中 字符串题目:竖直打印单词 - 图51 是字符串 字符串题目:竖直打印单词 - 图52 的单词数,字符串题目:竖直打印单词 - 图53 是字符串 字符串题目:竖直打印单词 - 图54 的最大单词长度。需要额外创建一个 字符串题目:竖直打印单词 - 图55 类型的数组用于存储竖直打印单词的结果。由于 Java 中的 字符串题目:竖直打印单词 - 图56 类型的对象不可变,因此空间复杂度至少为 字符串题目:竖直打印单词 - 图57#card=math&code=O%28nl%29&id=MDAIW)。