[Java][Leetcode hard] 68. 文本左右对齐

对于每一行的单词,有三种可能:

  • 一行只有一个单词,单词左对齐,然后后面多出来填充空格。
  • 最后一行,左对齐,每个单词填充一个空格,然后后面多出来填充空格。
  • 除了上面两种情况的常规行:一共共有maxWidth个位置,所有的单词共有wordLen,需要填充的空格数:maxWidth-wordLen。单词后填充的空格数:(maxWidth-wordLen)/(wordNums - 1)。剩余的空格为(maxWidth-wordLen)mod(wordNums - 1)依次填充到左边的空格中。

1. 按照上述思路自己想的:

java 复制代码
class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
       List<String> res = new ArrayList<>();

        StringBuilder sb = new StringBuilder();
        int lineLen = 0;
        int lineWordNum = 0;
        for(int i = 0;i< words.length;i++){
            // 判断是不是单行单词
            int curLen = words[i].length();
            if(lineWordNum == 0 && i  < words.length - 1 && curLen + 1 + words[i+1].length() > maxWidth ){
                sb.append(words[i]);
                sb.append(repeatSpaces(maxWidth - curLen));

                res.add(sb.toString());
                sb = new StringBuilder();
            }else {

                // 常规行
                if(lineLen + curLen + lineWordNum  > maxWidth){
                    // 这一行放不下这个单词了

                    // 三个单词至少有两个空格 lineWordNum + 1 -1;
                    // 加上这个单词超出最大宽度了

                    int avgSpaceNum = (maxWidth - lineLen)/(lineWordNum -1);
                    int remainSpaceNum =  (maxWidth - lineLen)%(lineWordNum -1);
                

                    for(int j = lineWordNum-1; j>=0 ;j--){
                        sb.append(words[i -1 -j]);
                        if(j != 0){
                            sb.append(repeatSpaces(avgSpaceNum));
                            if(remainSpaceNum-- > 0) sb.append(" ");
                        }
                    }

                    lineLen = 0;
                    lineWordNum = 0;
                    res.add(sb.toString());
                    sb = new StringBuilder();
                    
                    i = i-1;  // 返回去重新处理这个单词

                }else{
                    // 这个单词可以放得下
                    lineLen += curLen;
                    lineWordNum++;


                    // 最后一行
                    if(i == words.length - 1){
                        for(int j = lineWordNum-1; j>=0 ;j--){
                            sb.append(words[i-j]);
                            if( j!= 0) sb.append(" ");
                        }
                        sb.append(repeatSpaces(maxWidth - sb.length()));
                        res.add(sb.toString());
                    }
                }
            }
        }

        return res;
    }
    public String repeatSpaces(int num){
        StringBuilder sb  = new StringBuilder();
        while(num -- > 0)  sb.append(" ");
        return sb.toString();
    }
}

使用贪心算法优化

  • 应用贪心的思想,先看本行一共能装多少个单词
  • 然后把情况分成两种:1.左对齐 2.常规行;简化操作。
java 复制代码
class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
       List<String> res = new ArrayList<>();

       int n = words.length;
       int i = 0;
       while(i < n){
          // 遍历到第i个元素
          int curLen = words[i].length();
          int curIndex = i + 1; 

          // 贪心算法,尽可能的往这一行多放单词(单词之间至少要一个空格)
          while(curIndex < n){
             if(curLen + 1 + words[curIndex].length() > maxWidth) break;
             curLen += 1 + words[curIndex].length();
             curIndex++;
          }
          
           StringBuilder sb = new StringBuilder();
           int wordCount = curIndex - i; 
           int gaps =  wordCount - 1 ;

           // 情形1:左对齐的情况:最后一行或者单个单词行
           if(curIndex == n ||  wordCount == 1){
                for(int j = i;j<curIndex ;j++){
                    sb.append(words[j]);
                    if (j!=curIndex-1) sb.append(" ");
                }
                sb.append( repeatSpaces(maxWidth - sb.length()));
           }else{
            // 情形2:常规行
              int spaceNum = maxWidth - curLen + gaps; // 多减的单词间的分隔空格要加回来
              int avgSpaceNum = spaceNum / gaps;
              int remainSpaceNum =  spaceNum % gaps;

              for(int j = i; j < curIndex ;j++){
                        sb.append(words[j]);
                        if(j != curIndex-1){
                            sb.append(repeatSpaces(avgSpaceNum));
                            if(remainSpaceNum-- > 0) sb.append(" ");
                        }
               }
           }

           res.add(sb.toString());
           i = curIndex; // 处理下一个单词
       }

       return res;
    }
    public String repeatSpaces(int num){
        StringBuilder sb  = new StringBuilder();
        while(num -- > 0)  sb.append(" ");
        return sb.toString();
    }
}
相关推荐
贫民窟的勇敢爷们4 小时前
SpringBoot整合AOP切面编程实战,实现日志统一记录+接口权限校验
java·spring boot·spring
jerryinwuhan4 小时前
基于各城市站点流量的复合功能比较
开发语言·php
浅念-4 小时前
递归解题指南:LeetCode经典题全解析
数据结构·算法·leetcode·职场和发展·排序算法·深度优先·递归
AC赳赳老秦4 小时前
供应链专员提效:OpenClaw自动跟踪物流信息、更新库存数据,异常自动提醒
java·大数据·服务器·数据库·人工智能·自动化·openclaw
迈巴赫车主4 小时前
Java基础:list、set、map一遍过
java·开发语言
灵犀学长5 小时前
基于 Spring ThreadPoolTaskScheduler + CronTrigger 实现的动态定时任务调度系统
java·数据库·spring
洛水水5 小时前
【力扣100题】33.验证二叉搜索树
算法·leetcode·职场和发展
南 阳6 小时前
Python从入门到精通day66
开发语言·python
好家伙VCC6 小时前
【无标题】
java
十八旬7 小时前
快速安装ClaudeCode完整指南
开发语言·windows·python·claude