LeetCode68. 文本左右对齐

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

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

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

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

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

示例1:

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",
     因为最后一行应为左对齐,而不是左右两端对齐。       
     第二行同样为左对齐,这是因为这行只包含一个单词。

上面的题目描述还是略显啰嗦,我整理了一下

  • 尽可能多地往每行中放置单词
  • 均匀分配单词间的空格数量,如果不能均匀,左侧放置的空格数要多于右侧的空格数
  • 如果一行只能包含一个单词,左对齐
  • 文本的最后一行应为左对齐,且单词之间不插入额外的空格。

我的解答

/**
 * 68. 文本左右对齐(贪心,字符串,hard)<br>
 * https://leetcode-cn.com/problems/text-justification/<br>
 * 代码丑长,但ac87%,可以继续优化<br>
 * 估计只有刚写完的自己看得懂<br>
 * 踩了一些坑,还是要细心,考虑周全<br>
 * 
 * @author wuwang
 *
 */
class Solution {
	public List<String> fullJustify(String[] words, final int maxWidth) {
		int index = 0;
		final char sp = ' ';
		ArrayList<String> result = new ArrayList<>();
		while (index < words.length) {
			StringBuilder sb = new StringBuilder();
			int len = 0, count = 0, scount = 0;
			// 贪心greddy
			while (index + count < words.length && (len + words[index + count].length()) <= maxWidth) {
				len += words[index + count].length();
				++count;
				if (len < maxWidth) {
					++len;
					++scount;
				} else if (index + count < words.length) {
					if (len + words[index + count].length() == maxWidth) {
						++count;
						len += words[index + count].length();
					}
					break;
				}

			}

			len -= scount;// 所有单词的长度
			// 最后一行,左对齐,单词间不插入额外的空格
			if ((index + count) == (words.length)) {
//				System.out.printf("%s %s %s\n", index, count, words.length);
				int l = 0, i = index;
				for (; i < (words.length - 1); ++i) {
					sb.append(words[i]);
					sb.append(sp);
					l += words[i].length() + 1;
				}
				sb.append(words[i]);// 最后一个单词无空格
				l += words[i].length();
				while (l < maxWidth) {// 补空格
					sb.append(sp);
					++l;
				}
			} else if (count > 1) {// 一行多个单词,且尽可能均匀空格,如不能,左边空格多余右边

				int spaceHolderCount = count - 1;// 要填空格的空白处
				int spaceCount = maxWidth - len;// 空格数量
//				System.out.printf("%d %d\n", spaceHolderCount, spaceCount);
				for (int i = 0; i < count; ++i) {
					sb.append(words[index + i]);
					int n = 0;
					if (spaceHolderCount != 0)
						n = spaceCount / spaceHolderCount + ((spaceCount % spaceHolderCount) == 0 ? 0 : 1);// 运算符优先级的一个坑
					// n = spaceCount / spaceHolderCount +( (spaceCount % spaceHolderCount) == 0 ? 0
					// n = spaceCount / spaceHolderCount + spaceCount % spaceHolderCount == 0 ? 0:1;
					// 二目运算符优先级大于三目
					for (int j = 0; j < n; ++j) {// 填空格
						sb.append(sp);
					}
					spaceHolderCount -= 1;
					spaceCount -= n;
				}

			} else {// 只有一个单词,左对齐补空格即可
				sb.append(words[index]);
				for (int i = words[index].length(); i < maxWidth; ++i)
					sb.append(sp);
			}

			index += count;
			result.add(sb.toString());
		}

		return result;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值