LeetCode每日一题: 文本左右对齐

296 阅读3分钟

文本左右对齐

给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

说明:

单词是指由非空格字符组成的字符序列。
每个单词的长度大于 0,小于等于 maxWidth。
输入单词数组 words 至少包含一个单词。

示例:

输入:
    words = ["This", "is", "an", "example", "of", "text", "justification."]
    maxWidth = 16
输出:
[
   "This    is    an",
   "example  of text",
   "justification.  "
]

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/te… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


思路

  • 每一行都应该尽量多的放入单词;
  • 除了每行的最后一个单词外,每个单词后面至少有一个空格,否则单词就连接在一起了;
  • 空格需要均匀的分布到单词中间,多余的空格,需要从左往右挨个分配;
  • 最后一行每个单词后有且只有一个空格,多余的空格放在最后面;

如题示例:

words = ["This", "is", "an", "example", "of", "text", "justification."] 
maxWidth = 16
"This", "is", "an" 这三个单词加起来是 8 位,如果再加上 "example" 就超过了 16;
那么第一行 必然由 "This", "is", "an" 这三个单词;
"This", "is" 后面必须存在一个空格,那么总长度为 10;
距离16 还需要补6 个 “ ”;需要均为分配再三个单词中间
于是有结果 "This【4个空格】is【4个空格】an"

第二行和第一行类似,但是单词长度加上必要的空格 长度为 15;
距离16 差 1个空格,但是不够所有空格均分,所以从左往右进行分配
于是有结果 "example【2个空格】of【1个空格】text"

最后一行,每个单词后有且只有一个空格,多余的空格放在最后面;
于是有结果 "justification.【2个空格】"

根据这样的思路,我们可以先计算每行的单词+必要的空格的长度,然后根据给的maxWidth计算出每个单词的后面需要均分多少个单词,然后根据多出来的单词再分配空格;

最后一行是一种特殊情况,每个单词后面只有一个空格,多余的空格加在最后面随意需要单独处理

题解

public List<String> fullJustify(String[] words, int maxWidth) {
    int sum = 0;
    int last = 0;
    List<int[]> sumList = new ArrayList<>();
    List<String> rtnStr = new ArrayList<>();
    for (int i = 0 ;i<words.length;i++) {
        if(sum+words[i].length()<=maxWidth){
            sum += words[i].length()+1;
            last++;
        }else {
            i--;
            sumList.add(new int[]{sum-1,last,i});
            sum = 0;
            last = 0;
        }
        if(i==words.length-1){
            sumList.add(new int[]{sum-1,last,i});
        }
    }
    // s[0] 对应行数 单词数目多少,s[1]几个单词;
    for (int i = 0; i < sumList.size(); i++) {
        int [] s = sumList.get(i);
        //x 表示 每个空格多少个 y表示余下多少个\
        int x = 0, y =maxWidth - s[0];
        if(s[1]-1 != 0){
            x = (maxWidth - s[0]+s[1]-1) / (s[1]-1);
            y = (maxWidth - s[0]+s[1]-1) % (s[1]-1);
        }
        StringBuilder stringBuilder = new StringBuilder();
        if(i<sumList.size()-1&&s[1]>1){
            for(int j=s[2]-s[1]+1 ; j<=s[2];j++){
                stringBuilder.append(words[j]);
                if(j!=s[2]){
                    for (int k = 0; k < x; k++) {
                        stringBuilder.append(" ");
                    }
                }
                if(j<=s[2]-s[1]+1+y){
                    stringBuilder.append(" ");
                }
            }
        }else {
            for(int j=s[2]-s[1]+1 ; j<=s[2];j++){
                stringBuilder.append(words[j]);
                if(j!=s[2]){
                    stringBuilder.append(" ");
                }
                if(j==s[2]){
                    int i1 = (x * (s[1] - 1) + y) - s[1]+1;
                    for (int k = 0; k < i1; k++) {
                        stringBuilder.append(" ");
                    }
                }
            }
        }

        rtnStr.add(stringBuilder.toString());
    }
    return rtnStr;
}

记录每日刷 leetcode 的思路 和 想法; 

见证每 1 bit 成长; 

在线蹲赞环节  

老板!点赞!