[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 分钟前
[Java] 用纯 Swing 做一个《論語·學而》阅读器
java·ai编程·交互设计
艾伦_耶格宇1 小时前
【kubernetes - 1.28版本】-11 K8S核心组件
java·容器·kubernetes
Dxy12393102161 小时前
JS AES加密详解
开发语言·javascript·ecmascript
2301_780789661 小时前
深度伪造即服务:新型网络诈骗的“完美面具”与识别之道
java·网络·ddos
信息安全失业大专人员1 小时前
每日了解一个智能体-WorkBuddy
开发语言·ai·c#·智能体
LHICOD1 小时前
Linux-2
java·linux·后端·jar·vmware·svm·vm
香蕉大香蕉(06敬畏市场)1 小时前
MySQL 单点详解(03)
java·数据库·mysql·面试·八股·大厂实习
4ever.ov01 小时前
精学C++第一站 从命名空间到引用:C++入门核心语法全梳理(13000字长文)
开发语言·c++·clion
小杨互联网1 小时前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
揽星河..1 小时前
【C语言】数组
c语言·开发语言·算法