68. 文本左右对齐

1,154 阅读3分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

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

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

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

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

说明:

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

示例:

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

解题思路

1、用数组vint存储每个字符串的长度;

2、定义一个字符串s,尽可能的往这个字符串里塞单词,怎么判断呢?

  • 定义一个整数sum,判断sum+vint[addr]是否大于maxWidth,大于则进行是否需要补空格操作,小于等于则sum=sum+vint[addr]+1;s=s+words[addr]+" "; +1是因为每个单词之间必须有一个空格,循环结束弹出末尾空格;

3、补空格操作:

  • 设需要补的空格数等于space,则space=space=maxWidth-sum+1; +1是因为末尾弹出了空格,在上一步字符串s操作时记录了插入单词个数size,因为除末行左对齐外,其余行只能在单词之间插入空格,此时size应当减一即size--,因为能放置空格的地方只有size--个。
  • 然后判断是否为末行addr>=words.size()且末行单词数大于1,即size>0;即addr>=words.size()&&size>0;则直接在末尾插入即可,若不是末行,分单词数量插入,一个单词即size==0;直接末尾插入空格即可,大于一个单词(在上一步字符串操作时记录了补空格的位置s_addr数组)则在s_addr[i]处插入空格,i表示应当在选择哪个s_addr处插入,更新s_addr保存的下标s_addr[i]=s_addr[i]+k;k表示每次在i处插入空格后面的下标都会往后移1位,然后进行i=i%size;即循环插入,当i==0时,k清零;

4、ans尾部放入s

代码

class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<int> vint;
        vector<string> ans;
        for(auto &x:words){//存储每个字符串的长度
            vint.push_back(x.size());
        }

        int addr=0;
        while(addr<words.size()){
            int sum=0;
            string s;
            int size=0;
            vector<int> s_addr;
            while(sum+vint[addr]<=maxWidth){//尽可能放置字符串
                sum+=vint[addr]+1;
                s=s+words[addr]+" ";
                s_addr.push_back(sum-1);
                addr++;//记录位置
                size++;//记录单词数量
                if(addr>=words.size()) break;
            }
            s.pop_back();//弹出末尾空格
            int space=maxWidth-sum+1;//记录需要补录的空格数量
            size--;//插入空格的地方有几处
            if(addr>=words.size()&&size>0)//判断是否为末行
            {//是末行
                while(space>0){
                    s.push_back(' ');
                    space--;
                }
            }else{//不是末行
                if(space>0){
                int i=0;
                int k=0;
                while(space>0){
                    if(size!=0){//不是一个单词,循环插入空格,这里觉得判断while(space>0)外部更好,减少判断次数
                        s.insert(s_addr[i]+k,1,' ');
                        s_addr[i]=s_addr[i]+k;//更新下标
                        i++;
                        i=i%size;//循环下标
                        k++;
                        if(i==0)k=0;//k清零
                        space--;
                    }else{//是一个单词
                        s.push_back(' ');//直接末尾添加
                        space--;
                    }
                }
                }
            }
            
            ans.push_back(s);
        }
        return ans;
    }
};