leetcode
leetcode 1251 ~ 1300
竖直打印单词

竖直打印单词

难度:

标签:

题目描述

代码结果

运行时间: 20 ms, 内存: 15.9 MB


/**
 * 思路:
 * 1. 通过流的方式将输入字符串按空格分割成单词数组。
 * 2. 计算最长单词的长度。
 * 3. 使用流创建每一列的字符串,同时使用StringBuilder构建并通过map和collect收集结果。
 * 4. 使用map操作去除末尾的空格。
 */
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.List;
import java.util.Arrays;

public List<String> printVerticallyStream(String s) {
    // 分割字符串成单词数组
    String[] words = s.split(" ");
    // 计算最长单词的长度
    int maxLength = Arrays.stream(words).mapToInt(String::length).max().orElse(0);
    // 创建结果列表
    return IntStream.range(0, maxLength)
            .mapToObj(i -> Arrays.stream(words)
                    .map(word -> i < word.length() ? String.valueOf(word.charAt(i)) : " ")
                    .collect(Collectors.joining()))
            .map(str -> str.replaceAll("\\s+$", ""))
            .collect(Collectors.toList());
}

解释

方法:

题解的核心思想是先将输入字符串s按空格分割成单词列表,然后找出最长单词的长度。这一长度决定了输出列表中字符串的数量,即最终结果的高度。接着,对于每一个可能的字符位置(从0开始,直到最长单词的长度),从每个单词中尝试取出对应位置的字符,若当前单词长度不足,则用空格代替。这样,我们可以构建出每一列的字符串。由于输出不允许有尾随空格,因此每构建完一列后,需要对其进行右侧空格的剪裁。

时间复杂度:

O(n + m*k)

空间复杂度:

O(m*k)

代码细节讲解

🦆
在题解中,为什么在处理每列的字符时选择使用列表推导式和条件表达式,而不是其他循环或条件结构?
列表推导式和条件表达式的使用提供了一种简洁且高效的方式来构建列表,特别是在需要从多个源(这里是不同单词)按条件(对应位置的字符存在与否)提取元素的场景中。使用列表推导式,可以直接在一个表达式中完成迭代、条件判断和列表生成,这样的代码不仅简洁,而且易于理解和维护。相比之下,使用传统的循环和条件结构可能会使代码更加冗长和复杂。
🦆
题解提到最终结果要剪裁右侧空格,具体是如何确定每列字符串中的尾随空格数量的?
在构建每一列的字符串完成后,可以通过字符串的 `rstrip()` 方法来移除尾部的空格。这个方法会检查字符串尾部的连续空格,并将它们从字符串中删除,直到遇到一个非空格字符为止。这种方法不需要预先知道尾随空格的具体数量,因为 `rstrip()` 会自动处理这些空格。
🦆
你是如何保证每个单词只在一列上打印,并且列之间不会相互影响的?
在构建列字符串的过程中,每次迭代都是独立处理每个单词对应位置的字符。如果单词长度足够,则取出该位置的字符;如果不足,则添加空格。这样,每一次迭代都独立生成一列字符串,并且每个单词的贡献是独立的,互不影响。在整个过程中,由于不同列的字符串是在不同的迭代中生成的,因此列与列之间自然是隔离的。
🦆
输出的每一列字符串是如何处理和保证没有尾随空格的?
每一列字符串生成后,使用字符串的 `rstrip()` 方法来剪裁掉右侧的空格。这个方法确保了每一列的输出都不会包含不必要的尾随空格,从而满足题目的要求。这种处理方式是自动的,并且效率高,因为它避免了额外的空格计数或迭代。

相关问题