Leetcode ---- 68.文本左右对齐

题目:

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

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

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

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

说明:

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

示例:

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

示例 2:

输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
[
  "What   must   be",
  "acknowledgment  ",
  "shall be        "
]
解释: 注意最后一行的格式应为 "shall be    " 而不是 "shall     be",
     因为最后一行应为左对齐,而不是左右两端对齐。       
     第二行同样为左对齐,这是因为这行只包含一个单词。

示例 3:

输入:
words = ["Science","is","what","we","understand","well","enough","to","explain",
         "to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
输出:
[
  "Science  is  what we",
  "understand      well",
  "enough to explain to",
  "a  computer.  Art is",
  "everything  else  we",
  "do                  "
]

思路:

这道题需要考虑的方面相对多一点,需要仔细理清思路。

扫描二维码关注公众号,回复: 3600199 查看本文章

首先,看完题目我们可以了解有以下限制条件:

1. 每行首尾两单词是两端对齐的,中间的空格数是先均匀分布,然后再从左往右分布剩下的。

2. 中间存在一个单词的,直接靠左,剩余补全空格。

3. 最后一行无需两端对齐,每个单词间一个空格即可。

知道以上条件后,我们可以先求出所需要的行数,每个单词所在的行数标签。

然后再求出每个单词间的空格数,且存入string对象。

循环多次,即可得到vector<string>对象。

该思路所对应的程序是注释掉的,由于比较繁琐,所以参考了网上更优的方法。它的思路和本思路类似,但是它是一边处理一边存储,效率高很多。

程序:(注释掉的是自己写的,非注释是后来参考别人的)

class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> res;
        int left = 0;   // 行索引
        int wordsNum = words.size();
        while(left < wordsNum){
            int right = left, len = 0;
            while(right<wordsNum && len+words[right].size()+right-left<=maxWidth)
                len += words[right++].size();   // right - left : 首尾两单词间空格数
            string temp;
            int space = maxWidth - len; // 行空格数
            for(int i=left;i<right;i++){    // right:行单词数
                temp += words[i];
                if(space > 0){  // 单词后加空格
                    int snum; // 单词间空格数
                    if(right == wordsNum){  // 最后一行
                        if(right-i == 1) // 只有一个单词
                            snum = space;
                        else 
                            snum = 1;
                    }
                    else{   // 前几行
                        if(right-i-1 > 0){  // right-1: 行单词数尾下标 [0,right-1]
                            if(space%(right-i-1) == 0) 
                                snum = space/(right - i - 1);
                            else 
                                snum = space/(right - i - 1) + 1;
                        }
                        else // 只有一个元素
                            snum = space;
                    }
                    temp.append(snum,' ');
                    space -= snum;  // 更新剩余空格数
                }
            }
            res.push_back(temp);
            left = right;   // 更新行索引
        }
        return res;        
      /*  int rest = maxWidth;
        int space = 0;
        int wordsNum = words.size();
        int row = 0;
        cout << "num: " << wordsNum << endl;
        int index[wordsNum] = {0};
        int wordsLen = 0;

        for (int i=0;i<wordsNum;i++){
            int tmp_i = i;
            wordsLen = words[i].size(); 
            if (rest >= (wordsLen + space)){   // 4 >= 15 ? 
                rest = rest - wordsLen - space;
                space = 1;
            }
            else{
                ++row;     // 总行数
                i = tmp_i - 1;
                space = 0;
                rest = maxWidth;
            }
            if (i == tmp_i){
                index[i] = row;   // 各个单词的所在行
                cout << index[i] << endl;                
            }
        }
        
        int wordsOfRow[row+1] = {0};    // 每行的字符数
        int rowArr[row+1] = {0};        // 每行的单词数
        int spaceAdd = 0;
        int tmp = 0;
        vector<string> str; 
        int in = 0; // 行首索引
        
        for (int j=0;j<row+1;j++){
            for (int i=0;i<wordsNum;i++){     // 每行的单词数和字符个数
                if (index[i] == j){
                    wordsOfRow[j] += words[i].size();
                    rowArr[j]++;
                }
            }
            string tmpS;
            tmp = rowArr[j] - 1;    // 空格位数
            if (tmp == 0){   // 当行只有一个单词时
                tmpS = tmpS + words[in];
                for (int sp=0;sp<maxWidth-words[in].size();sp++){
                    tmpS = tmpS + " ";
                }
                str.emplace_back(tmpS);
                in++;   // 行索引加1
                cout << words[in-1] << endl;
            }
            else{   // 正常情况
                int spaceArr[tmp+1] = {0};    // 空格组
                int spaceSum = maxWidth - wordsOfRow[j];
                int avrg = spaceSum/tmp;
                spaceAdd = spaceSum % tmp;
                for (int k=0;k<tmp;k++){
                    spaceArr[k] =  avrg;
                } 
                for (int k=0;k<spaceAdd;k++){
                    spaceArr[k] +=  1;
                }   
                if (j == row){  // 当最后一行时
                    tmpS = words[in];
                    int l=1;
                    for (;l<rowArr[j];l++){
                        tmpS = tmpS + " " + words[in+l];                
                    }
                    tmpS.append((spaceSum-rowArr[j]+1),' ');
                }
                else{
                    for (int l=0;l<rowArr[j];l++){
                        tmpS = tmpS + words[in+l];
                        for (int sp=0;sp<spaceArr[l];sp++){
                            tmpS = tmpS + " ";
                        }       
                    }                    
                }
                str.emplace_back(tmpS);
                in += rowArr[j];    // 修正行首索引
            }        
        }
        return str;*/
    }
};

猜你喜欢

转载自blog.csdn.net/hc372893308/article/details/83057430
今日推荐