力扣经典150题第二十四题:文本左右对齐

简介: 力扣经典150题第二十四题:文本左右对齐

力扣经典150题解析之二十四:文本左右对齐

1. 介绍

在这篇文章中,我们将讨论力扣经典150题中的第二十四题:文本左右对齐问题。给定一个单词数组 words 和一个长度 maxWidth,我们需要重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

2. 问题描述

给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ’ ’ 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

注意:

单词是指由非空格字符组成的字符序列

每个单词的长度大于 0,小于等于 maxWidth。

输入单词数组 words 至少包含一个单词。

3. 示例

示例 1:

输入: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
输出:
[
   "This    is    an",
   "example  of text",
   "justification.  "
]

示例 2:

输入: words = ["What","must","be","acknowledgment","shall","be"], maxWidth = 16
输出:
[
  "What   must   be",
  "acknowledgment  ",
  "shall be        "
]

示例 3:

输入: words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","we","do"], maxWidth = 20
输出:
[
  "Science  is  what we",
  "understand      well",
  "enough to explain to",
  "a  computer.  Art is",
  "everything  else  we",
  "do                  "
]

4. 解题思路

我们可以使用贪心算法来解决这个问题:

  1. 遍历单词数组 words,逐行构建文本。
  2. 维护一个变量 current_line 来存储当前行的单词列表。
  3. 不断尝试将单词添加到当前行,同时考虑单词之间的空格。
  4. 如果添加下一个单词会导致行长度超过 maxWidth,则进行对齐处理:计算需要插入的空格数,并生成对齐后的字符串。
  5. 特别处理最后一行,确保左对齐而不是两端对齐。

5. 代码实现

import java.util.ArrayList;
import java.util.List;
public class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
        List<String> result = new ArrayList<>();
        int start = 0;
        
        while (start < words.length) {
            int end = start;
            int lineLength = 0;
            
            // Calculate the words and total length for the current line
            while (end < words.length && lineLength + words[end].length() + (end - start) <= maxWidth) {
                lineLength += words[end].length();
                end++;
            }
            
            // Build the current line
            StringBuilder line = new StringBuilder();
            int numOfWords = end - start;
            int numOfGaps = numOfWords - 1;
            
            // If it's the last line or only one word in the line
            if (end == words.length || numOfWords == 1) {
                for (int i = start; i < end; i++) {
                    line.append(words[i]);
                    if (i < end - 1) line.append(" ");
                }
                while (line.length() < maxWidth) line.append(" ");
            } else {
                // Calculate spaces distribution for other lines
                int totalSpaces = maxWidth - lineLength;
                int spacesBetweenWords = totalSpaces / numOfGaps;
                int extraSpaces = totalSpaces % numOfGaps;
                
                for (int i = start; i < end; i++) {
                    line.append(words[i]);
                    if (i < end - 1) {
                        for (int j = 0; j < spacesBetweenWords; j++) {
                            line.append(" ");
                        }
                        if (extraSpaces > 0) {
                            line.append(" ");
                            extraSpaces--;
                        }
                    }
                }
            }
            
            result.add(line.toString());
            start = end;
        }
        
        return result;
    }
}

6. 复杂度分析

  • 时间复杂度:O(n),其中 n 是单词数组 words 的长度。每个单词只需要遍历一次。
  • 空间复杂度:O(1),除了结果存储之外,只使用了常数级别的额外空间。

7. 测试与验证

我们对示例输入进行测试:

public class Main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        String[] words1 = {"This", "is", "an", "example", "of", "text", "justification."};
        int maxWidth1 = 16;
        List<String> result1 = solution.fullJustify(words1, maxWidth1);
        System.out.println("输出1:");
        for (String line : result1) {
            System.out.println("\"" + line + "\"");
        }
        
        String[] words2 = {"What","must","be","acknowledgment","shall","be"};
        int maxWidth2 = 16;
        List<String> result2 = solution.fullJustify(words2, maxWidth2);
        System.out.println("\n输出2:");
        for (String line : result2) {
            System.out.println("\"" + line + "\"");
        }
        
        String[] words3 = {"Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","we","do"};
        int maxWidth3 = 20;
        List<String> result3 = solution.fullJustify(words3, maxWidth3);
        System.out.println("\n输出3:");
        for (String line : result3) {
            System.out.println("\"" + line + "\"");
        }
    }
}

输出结果为:

输出1:
"This    is    an"
"example  of text"
"justification.  "
输出2:
"What   must   be"
"acknowledgment  "
"shall be        "
输出3:
"Science  is  what we"
"understand      well"
"enough to explain to"
"a  computer.  Art is"
"everything  else  we"
"do 

8. 总结

通过贪心算法,我们成功解决了文本左右对齐的问题。在构建每一行时,我们尽可能多地放置单词,并通过均匀分配空格的方式对齐文本。特别地,我们要注意处理最后一行,确保左对齐而不是两端对齐。

9. 扩展

我们可以探讨一些扩展话题,例如使用其他算法(如动态规划)来解决文本对齐问题的优化方案,或者讨论特殊情况和边界条件下的处理方式。

希望本文能够帮助读者理解文本左右对齐问题及其解决方法。


这篇博客按照目录结构组织了问题描述、解题思路、代码实现和复杂度分析等内容,希望对您有所帮助!

相关文章
|
6月前
|
算法
每日一题:LeetCode-75. 颜色分类
每日一题:LeetCode-75. 颜色分类
|
5月前
|
算法 索引 Perl
力扣经典150题第二十二题:Z 字形变换
力扣经典150题第二十二题:Z 字形变换
38 1
|
5月前
|
算法
力扣经典150题第三十七题:矩阵置零
力扣经典150题第三十七题:矩阵置零
31 2
|
5月前
|
存储 算法 测试技术
力扣经典150题第三十三题:最小覆盖子串
力扣经典150题第三十三题:最小覆盖子串
35 1
|
5月前
|
算法
力扣经典150题第十九题:最后一个单词的长度
力扣经典150题第十九题:最后一个单词的长度
28 0
|
5月前
|
算法
力扣经典150题解析之三十四:有效的数独
力扣经典150题解析之三十四:有效的数独
41 0
|
5月前
|
存储 算法 程序员
力扣经典150题第三十一题:无重复字符的最长子串
力扣经典150题第三十一题:无重复字符的最长子串
31 0
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第2期】组合与排列问题系列
【经典LeetCode算法题目专栏分类】【第2期】组合与排列问题系列
|
算法
代码随想录算法训练营第二十五天 | LeetCode 216. 组合总和 III、17. 电话号码的字母组合
代码随想录算法训练营第二十五天 | LeetCode 216. 组合总和 III、17. 电话号码的字母组合
52 0
LeetCode每日一题(8)——二进制间距
二进制间剧 1.题目 2.示例 3.思路 4.代码 5.复杂度分析