leetcode
 
解题思路
文本左右对齐问题需要将单词数组按最大宽度排版,满足左右对齐规则,最后一行左对齐。核心思路是 贪心算法确定每行单词数 + 动态空格分配,具体步骤如下:
- 确定每行单词范围:贪心选择尽可能多的单词,确保单词总长度加最小空格数不超过 
maxWidth。 
- 生成每行字符串:
- 普通行:均匀分配空格,左侧优先多放空格。
 
- 最后一行或单单词行:左对齐,行末补剩余空格。
 
 
关键步骤
- 行划分:通过遍历确定每行的起始和结束单词索引,并计算总单词长度。
 
- 空格分配:
- 普通行:总空格数按单词间隔分配,余数优先给左侧。
 
- 最后一行:单词间仅一个空格,剩余空格补在末尾。
 
 
- 高效构建字符串:使用 
strings.Builder 避免频繁字符串拼接的性能问题。 
复杂度分析
- 时间复杂度:O(n),每个单词被遍历一次。
 
- 空间复杂度:O(m),存储结果数组的长度(m 为行数)。
 
代码实现
func fullJustify(words []string, maxWidth int) []string {
    var result []string
    start := 0
    n := len(words)
    for start < n {
        // 确定当前行的结束索引和单词总长度
        end, sumWordLen := findEnd(words, start, maxWidth)
        // 生成当前行的字符串
        line := buildLine(words, start, end, sumWordLen, maxWidth, end == n-1)
        result = append(result, line)
        start = end + 1
    }
    return result
}
// 找到当前行的结束索引和单词总长度
func findEnd(words []string, start, maxWidth int) (int, int) {
    sumWordLen := 0
    end := start
    for end < len(words) {
        currentWordLen := sumWordLen + len(words[end]) // 尝试添加当前单词
        requiredSpace := end - start                   // 当前行已包含的空格数(单词数-1)
        totalLength := currentWordLen + requiredSpace  // 总长度(单词+空格)
        if totalLength > maxWidth {                    // 超过最大宽度则停止
            return end - 1, sumWordLen
        }
        sumWordLen = currentWordLen // 更新总单词长度
        end++
    }
    return end - 1, sumWordLen // 处理到最后一个单词的情况
}
// 构建单行字符串
func buildLine(words []string, start, end, sumWordLen, maxWidth int, isLastLine bool) string {
    var builder strings.Builder
    wordCount := end - start + 1
    totalSpaces := maxWidth - sumWordLen
    // 处理最后一行或单单词行:左对齐,末尾补空格
    if wordCount == 1 || isLastLine {
        for i := start; i <= end; i++ {
            if i > start {
                builder.WriteByte(' ')
            }
            builder.WriteString(words[i])
        }
        remainingSpaces := maxWidth - builder.Len()
        builder.WriteString(strings.Repeat(" ", remainingSpaces))
        return builder.String()
    }
    // 普通行:均匀分配空格,左侧优先多放
    slots := wordCount - 1
    baseSpace := totalSpaces / slots
    extraSpace := totalSpaces % slots
    builder.WriteString(words[start])
    for i := 0; i < slots; i++ {
        space := baseSpace
        if i < extraSpace { // 前 extraSpace 个间隙多1空格
            space++
        }
        builder.WriteString(strings.Repeat(" ", space))
        builder.WriteString(words[start+i+1])
    }
    return builder.String()
}
 
 
 
代码解析
- 行划分逻辑 (
findEnd):
- 逐个添加单词,计算当前行的总长度(单词长度 + 最小空格数),直到超过 
maxWidth。 
- 返回当前行的结束索引和单词总长度。
 
 
- 字符串构建 (
buildLine):
- 最后一行/单单词行:左对齐,末尾补足空格。
 
- 普通行:计算每个间隔的基础空格数和余数,优先将余数分配给左侧间隔。
 
 
- 高效字符串操作:使用 
strings.Builder 减少内存分配次数,提升性能。 
运行示例
func main() {
    // 示例1
    words1 := []string{"This", "is", "an", "example", "of", "text", "justification."}
    fmt.Println(fullJustify(words1, 16))
    // 输出: [This    is    an example  of text justification.  ]
    // 示例2
    words2 := []string{"What", "must", "be", "acknowledgment", "shall", "be"}
    fmt.Println(fullJustify(words2, 16))
    // 输出: [What   must   be acknowledgment   shall be        ]
}
 
 
 
关键点
- 贪心选择行单词:确保每行尽可能多放单词,避免回溯。
 
- 空格分配策略:普通行均匀分配余数空格,最后一行强制左对齐。
 
- 边界处理:单单词行和最后一行需特殊处理,避免多余计算。