探究文本完全对齐技术:从理论到代码

news2024/11/25 2:42:19

文本完全对齐算法解析与实现

引言

在编辑文档、设计书籍版面或网页时,通常需要将文本进行格式化对齐,以提升视觉吸引力和易读性。

一种广泛采用的对齐技术是所谓的“完全对齐”,这意味着文本的每一行的起始和结束位置都要对齐整齐。

虽然许多现代文本编辑软件都支持这种对齐方式,但对于开发人员来说,手动实现该功能却是一项挑战。

本文将深入阐述如何利用Java语言完成文本的完全对齐。

在这里插入图片描述

问题描述

假设我们有一个单词数组 words 和一个整数 maxWidth,表示每行的最大宽度。我们的目标是将这些单词排版成一个文本块,使得每行恰好有 maxWidth 个字符,且左右两端对齐。如果某一行不能均匀分配空格,则左侧的空格数量要比右侧多。最后一行应为左对齐,并且单词之间不应插入额外的空格。

解决方案

为了解决这个问题,我们可以采用贪心算法结合双指针的技术来实现。下面将逐步介绍这一过程。

设计思路

  1. 初始化

    • 创建一个 List<String> 用于存储排版后的每一行。
    • 初始化两个指针 indexcur,分别指向当前处理的单词起始位置和尝试添加到当前行的下一个单词的位置。
    • 初始化一个整型变量 len 用于跟踪当前行已使用的字符总数。
  2. 循环处理每一行

    • 使用 while 循环迭代整个单词数组。
    • 在循环内部,再使用一个 while 循环来确定可以添加到当前行中的单词数量。条件是当前行加上新单词的长度(包括单词间的空格)不超过 maxWidth
  3. 构建当前行

    • 创建一个 StringBuilder 用于构建当前行。
    • 判断当前行是否是最后一行或仅包含一个单词,如果是,则将所有单词添加到 StringBuilder 中,并在单词之间添加单个空格。然后,在行末添加足够的空格以达到 maxWidth
    • 如果当前行不是最后一行并且包含多个单词,那么计算出单词之间应该有多少个基础空格以及需要额外添加空格的数量。然后将这些空格分配给单词之间。
  4. 添加当前行 到 结果列表

    • 将构建好的当前行字符串添加到结果列表中。
  5. 更新指针

    • index 更新为 cur + 1,以便下一次循环处理下一组单词。
  6. 返回结果

    • 当所有单词都被处理完毕后,返回结果列表。
实现细节
  • 空格分配:对于非最后一行,使用除法 (maxWidth - len) / (cur - index) 来计算基础空格数量,使用取模运算 (maxWidth - len) % (cur - index) 来获取剩余的空格,这些空格将从左到右依次分配给各单词间的空隙。
  • 特殊处理:对于最后一行或者只有一个单词的情况,使用左对齐,并在行尾填充剩余的空格。
  • StringBuilder:使用 StringBuilder 来构建每一行,因为它提供了高效的字符串操作方法,如 append(),适合动态构造字符串。
示例代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TextJustifier {

    /**
     * 将单词数组排版成每行恰好有 maxWidth 个字符的文本,左右两端对齐。
     *
     * @param words     单词数组
     * @param maxWidth  每行的最大宽度
     * @return          排版后的文本行列表
     */
    public List<String> justifyText(String[] words, int maxWidth) {
        List<String> justifiedLines = new ArrayList<>();
        int index = 0;

        while (index < words.length) {
            int len = 0;
            int cur = index;
            // 计算当前行可以容纳的单词数量
            while (cur < words.length && len + words[cur].length() + (cur - index) <= maxWidth) {
                len += words[cur++].length();
            }
            cur--; // 回退到实际的单词位置

            // 创建一个字符串构建器来拼接当前行
            StringBuilder lineBuilder = new StringBuilder();

            if (cur == words.length - 1 || index == cur) { // 最后一行或只有一个单词的情况
                for (int i = index; i <= cur; i++) {
                    lineBuilder.append(words[i]);
                    if (i < cur) {
                        lineBuilder.append(' '); // 单词间至少有一个空格
                    }
                }
                // 补足到最大宽度
                lineBuilder.append(" ".repeat(maxWidth - lineBuilder.length()));
            } else { // 其他情况
                int baseSpaces = (maxWidth - len) / (cur - index); // 基础空格数
                int extraSpaces = (maxWidth - len) % (cur - index); // 额外空格数

                // 分配空格
                for (int i = index; i <= cur; i++) {
                    lineBuilder.append(words[i]);
                    if (i < cur) {
                        lineBuilder.append(" ".repeat(baseSpaces + (i - index < extraSpaces ? 1 : 0)));
                    }
                }
            }

            // 添加当前行 到 结果列表
            justifiedLines.add(lineBuilder.toString());
            index = cur + 1; // 更新单词索引
        }

        return justifiedLines;
    }

    public static void main(String[] args ) {
        TextJustifier justifier = new TextJustifier();
        String[] words = {"This", "is", "an", "example", "of", "text", "justification."};
        int maxWidth = 16;
        List<String> justifiedText = justifier.justifyText(words, maxWidth);
        justifiedText.forEach(System.out::println);
    }
}

在这里插入图片描述

问题1:

1.为什么 lineBuilder.append(" ".repeat(maxWidth - lineBuilder.length()));爆红

在这里插入图片描述
因为我的jdk为1.8,repeat在java11中引用

替换

// 补足到最大宽度
                int remainingSpaces = maxWidth - lineBuilder.length();
                for (int i = 0; i < remainingSpaces; i++) {
                    lineBuilder.append(' ');

问题2:基础知识理解

问题:
具体来说,当文本被完全对齐时,每行的单词和空格是如何分布的?

答:如果空格不能均匀分配,那么左侧的空格数量要多于右侧的空格数量。最后一行则是左对齐的,单词之间有一个空格,行尾填充空格以达到规定的最大宽度。

问题3:复杂度分析

问题:
请分析你实现的算法的时间复杂度和空间复杂度,并解释为什么。

考察点:

  • 对算法复杂度的理解。
  • 能否合理评估算法性能。

答:
时间复杂度:O(n),其中 n 是单词数组 words 的长度。每个单词最多被处理一次,因此时间复杂度为线性。

空间复杂度:O(m),其中 m 是结果行的数量。最坏情况下,每行只有一个单词,因此空间复杂度取决于单词的数量。

问题4:优化与改进

问题:
如果需要进一步优化这个算法,你认为有哪些方面可以改进?例如,如何处理更大数据量的情况?

考察点:

  • 是否具备优化算法的思维。
  • 是否考虑过大规模数据处理的问题。

答:

空间优化:可以考虑使用 StringBuilder 直接构建最终的结果字符串,而不是使用 List 存储每一行。这样可以减少内存消耗。

并发处理:如果数据量非常大,可以考虑使用多线程来并行处理每一行,提高处理速度。
缓存机制:对于重复出现的单词组合,可以考虑使用缓存来避免重复计算空格分配。

问题5:异常处理

问题:
如果输入的 words 数组为空或 maxWidth 小于任何一个单词的长度,你的程序应该如何处理?

考察点:

  • 是否考虑到了异常情况。
  • 如何优雅地处理错误输入。

答:如果 words 数组为空,可以直接返回一个空列表。
如果 maxWidth 小于任何一个单词的长度,可以抛出一个异常,告知用户输入无效。

结论

通过上述方法,我们能够有效地实现文本的完全对齐,使得每一行的字符数固定,并且根据规则分配空格。这种方法不仅符合题目的要求,同时也具有较好的执行效率。希望本文能为你提供一个清晰的思路和实现方法,帮助你在实际项目中解决类似问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2125170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

暴雨液冷服务器硬刚液冷放量元年

AI&#xff08;人工智能&#xff09;不断向前&#xff0c;作为AI三驾马车之一&#xff0c;算力需求始终如影随形。 近日&#xff0c;财经记者走访了河南郑州多家服务器厂商、大模型公司和算力中心。在走访中&#xff0c;记者发现&#xff0c;液冷技术正被算力行业青睐&#xf…

3GPP How to manage a project?

有人问:"3GPP 每个release都做了哪些方面的增强&#xff1f;应该有专门的文档介绍吧?"那肯定是有的&#xff0c;其实按照 https://t.zsxq.com/zbSox 中的方法就能找到那个文档。这篇我们整体浏览看下3GPP是如何handle project&#xff0c;这其中就会具体涉及哪些内…

ctfshow-web入门-sql注入(web244-web247)error 报错注入

目录 1、web244 2、web245 3、web246 4、web247 1、web244 在它查询框这里随便输什么都没有回显 还是在 api 接口下传参&#xff0c;输入存在 id&#xff1a; /api/?id1 查询成功 输入不存在的 id&#xff1a; /api/?id0 查询失败 追加单引号后&#xff0c;报 sql 语法…

从零到一,数字文创IP是如何在基地中孵化成长的?

在数字时代的浪潮下&#xff0c;数字文创IP孵化基地正成为培育创新的肥沃土壤&#xff0c;见证着一个个数字文创 IP 从无到有、茁壮成长。 数字文创IP孵化基地首先为创意的萌发提供了空间。这里汇聚了各路富有创造力的人才&#xff0c;他们的思想在这里碰撞&#xff0c;灵感的火…

网络原理(3)—— 应用层、传输层(TCP)

1. 应用层 日常开发中最常用到的一层&#xff0c;主要涉及到两种情况&#xff1a; 1) 使用现成的应用层协议 2) 自己定义应用层协议 1.1 自定义应用层协议的流程 1. 明确前后端交互过程中需要传递哪些信息 实例&#xff1a;开发一个外卖软件 打开软件&#xff0c;首先需要展…

Win11安装mysql5.7.24

Win11安装mysql5.7.24 资源文件mysql安装过程 资源文件 mysql5.7.24免安装压缩包 下载链接&#xff1a; https://download.csdn.net/download/weixin_44174685/89738053 DirectX&#xff08;用来修复缺失dll&#xff09; 下载链接&#xff1a;https://download.csdn.net/downl…

App弱网测试是怎么测试的

一、网络测试的一般流程 step1&#xff1a;首先要考虑网络正常的情况 ① 各个模块的功能正常可用 ② 页面元素/数据显示正常 step2&#xff1a;其次要考虑无网络的情况 ① APP各个功能在无网络情况下是否可用 ② APP各个页面之间切换是否正常 ③ 发送网络请求时是否…

永成防回水防回气装置脚踏实地老厂家

永成防回水防回气装置脚踏实地老厂家&#xff0c;分歧式防爆器是安装在瓦斯抽放管路中的简易防爆装置。 来吧&#xff0c;有业务就冲着我来。 别让我的同行太辛苦&#xff0c; 我在这里&#xff0c;等你来。 本防回水防回气装置是一种用于煤矿瓦斯管路爆渣和燃烧时防止回火、防…

为什么说开放式耳机值得买?打工人通勤必备的蓝牙耳机推荐

开放式耳机值得购买&#xff0c;主要有以下几方面原因&#xff1a; 佩戴舒适性高&#xff1a; 不压迫耳道&#xff1a;开放式耳机不进入耳道&#xff0c;不会对耳道产生压迫&#xff0c;避免了入耳式耳机长时间佩戴可能导致的耳道疼痛、肿胀等不适状况。无论是小耳道用户&…

91、K8s之ingress上集

一、Ingress service模式&#xff1a; loadbalance NodePort&#xff1a;每个节点都会有一个指定的端口 30000-32767 内网 clusterip&#xff1a;默认模式&#xff0c;只能pod内部访问 externalName&#xff1a;需要dns提供域名 1.1、对外提供服务的ingress service&…

文献解读-The trans-omics landscape of COVID-19

关键词&#xff1a;流行病学&#xff1b;基因测序&#xff1b;变异检测&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;The trans-omics landscape of COVID-19 标题&#xff08;中文&#xff09;&#xff1a;COVID-19的跨组学全景 发表期刊&#xff1a…

【豆包Marscode体验官】爽了!直接口诉让豆包MarsCode 开发文章评论区BOT!

以下是「豆包 MarsCode 体验官」优秀文章&#xff0c;作者萌新杰少。 前言 不知道大家刷B站视频有没有注意到评论区下面会有人课代表&#xff0c;随后就会有一个B站的用户回复该视频的总结内容。 没有错&#xff01;我们今天就要复刻这个功能&#xff0c;不过是在掘金的评论区…

5G Multicast/Broadcast Services(MBS) (二) Multicast

这篇是Multicast handling的overview,正文开始。 值得注意的是,对于5MBS multicast,UE只有处于 RRC connected和Inactive时,网络侧才可以 通过MRB将MBS multicast数据传输到 UE;处于Idle态只能进行MBS broadcast过程。 对于multicast涉及的RN

防火墙、firewalld指令、更改yum源为阿里云的yum源及常见问题

一、防火墙分类 1、硬件防火墙 2、软件防火墙&#xff08;咱们昨天学的就属于这个&#xff09; 3、waf 4、下一代防火墙 二、工作原理 1、通过对进出口数据的&#xff08;数据、端口、IP等&#xff09;进行过滤&#xff0c;达到对内网数据的保护。 2、防护危险的一堵墙、…

Qt自定义按键实现长,短按

本文介绍Qt自定义按键实现长&#xff0c;短按。 Qt触摸屏应用有时会涉及到触摸屏按钮长&#xff0c;短按操作&#xff0c;如长按实现关机操作&#xff0c;本文基于普通QPushButton为基类&#xff0c;自定义按键实现长&#xff0c;短按操作。 1.定义新类 这里以QPushButton为…

电商|基于java的农业电商系统(源码+数据库+文档)

农业电商系统 目录 基于java的农业电商系统 一、前言 二、系统设计 三、系统功能设计 系统功能实现 前台&#xff1a; 后台&#xff1a; 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️…

ADC模数转换

ADC模数转换 ADC简介逐次逼近型ADC简介STM32的ADC外设 ADC的基本结构ADC输入通道规则组的转换模式单次转换&#xff0c;非扫描模式连续转换&#xff0c;非扫描模式单次转换&#xff0c;扫描模式连续转换&#xff0c;扫描模式 触发控制数据对齐转换时间校准可输出不同电压的电路…

ElasticSearch精要

1、什么是ElasticSearch&#xff1a; Elasticsearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎&#xff0c;每个字段都被索引并可被搜 索&#xff0c;可以快速存储、搜索、分析海量的数据。 集群&#xff1a;是一个或多个服务器的集合&#xff0c;共同保存数据并提供…

Assignment

1 Statement 里面包含了Expression。 对Statement 的interpret 里面包含了 对Expression 的interpret。 2 Expression 可以下降出Assignment 3 单个token前瞻递归下降解析器在解析完左侧操作数并偶然发现 之前&#xff0c;无法看清是否在解析赋值。毕竟&#xff0c;在解析完…

C语言补习课——文件篇

来源&#xff1a;黑马程序员 第157讲 C语言操作文件概述 读取文件&#xff1a;输入流 写文件&#xff1a;输出流 读写的方向判断取决与参照&#xff0c;一般我们站在程序的角度判断读写方向。 第158讲 路径 基本概念 路径就是指文件在电脑中的位置&#xff0c;eg&#xf…