[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();
    }
}
相关推荐
wjs20241 小时前
Rust 循环
开发语言
棋子入局1 小时前
C语言制作消消乐游戏(3)
c语言·开发语言·游戏
一直跑1 小时前
同一台服务器上(同局域网)的其他账号访问自己的数据(没有sudo权限和无 ACL和无共同组)
java·linux·服务器
l1t1 小时前
DeepSeek v4辅助编写调用Python包对用户数据做统计分析的页面
开发语言·javascript·python
°青1 小时前
JavaScript 核心知识点(四)
开发语言·前端·javascript
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 102. 二叉树的层序遍历 | C++ 极简 DFS 巧解
c++·leetcode·深度优先
梦想的颜色1 小时前
js document 节点增删改查、样式设计全解析
java·前端·javascript
zzb15801 小时前
「Kotlin 泛型深度图解:从入门到实战 + 委托框架揭秘」
开发语言·windows·kotlin
老友@2 小时前
Jenkins 中 Node 版本异常排查:Alpine + musl 导致的兼容问题(lts-alpine-jdk17)
java·servlet·jenkins