[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();
    }
}
相关推荐
无毁的湖光-Al几秒前
解Bug之路-隔离故障点后业务不恢复?-热点Key处理与亚稳态故障
java·数据库·mysql
yi0112 分钟前
LeetCode 3. 无重复字符的最长子串|不定长滑动窗口:什么时候更新最大值?
笔记·python·算法·leetcode·双指针·滑动窗口
kyle~5 分钟前
C++ 智能指针:RAII、所有权与对象生命周期
开发语言·c++
Eyfcom6 分钟前
快递管理系统中的电子围栏实战:高德与谷歌双平台技术选型与实现
java·后端·快递管理系统
Rain的Java大神之路7 分钟前
Java PDF导出,90%的人选错库!11个生产坑+选型+代码,一次讲透
java·后端·面试
y1su9 分钟前
Leetcode 单调栈模板
java·开发语言·数据结构·算法·leetcode
2601_9628857215 分钟前
如何用 Python 计算索提诺比率和卡玛比率?
开发语言·python
郑州光合科技余经理22 分钟前
出海外卖平台:支付对接为什么要和下单收款分开
android·java·开发语言·前端·后端·php·ai编程
我是人✓28 分钟前
Spring框架的事务管理
java·后端·spring
kimnoic29 分钟前
Python操作MySQL数据库的两种方式实例分析【pymysql和pandas】
开发语言·python