전체 단어배열을 받고, 하나의 줄의 길이를 input으로 받아서 조건에 맞는 문자열 배열을 반환한다
예제를 통해서 조건을 살펴보자
Input: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
Output:
[
"This is an",
"example of text",
"justification. "
]
"This", "is", "an", “example”
글자는 총 15글자이기 때문에 첫번째 줄에 들어갈수 있을 것 같지만 모든 단어와 단어 사이에는 기본적으로 “ ”
space가 들어가야 하기 때문에 최대 글자수 16을 넘어서 "This", "is", "an"
까지만 들어간다"example of text"
두번째 줄에서 첫번째 띄어쓰기 에서는 “ ”
space 가 두개, 두번째 띄워쓰기 에서는 “ ”
space 가 한개인것을 확인할 수 있다. 이거는example
of
text
이렇게 3개의 단어를 넣으면 총 13개의 공간을 차지하고, 3개의 띄어쓰기 공간이 남는데는 될수가 없고
“exampleof*text”` 가 되어야 한다는 말이다package algorithmn.textJustification;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static List<String> fullJustify(String[] words, int maxWidth) {
List<List<String>> outString = new ArrayList<>();
List<List<Integer>> outNumSpace = new ArrayList<>();
justifyRecursive(0, words, outString, outNumSpace, maxWidth);
List<String> result = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < outString.size() - 1; ++i) {
List<String> line = outString.get(i);
List<Integer> numSpaces = outNumSpace.get(i);
sb.append(line.get(0));
for (int j = 1; j < line.size(); ++j) {
int space = numSpaces.get(j - 1);
String word = line.get(j);
sb.append(" ".repeat(Math.max(0, space)));
sb.append(word);
}
// add padding
int padding = maxWidth - sb.length();
sb.append(" ".repeat(Math.max(0, padding)));
result.add(sb.toString());
sb.setLength(0);
}
sb.setLength(0);
List<String> lastLine = outString.get(outString.size() - 1);
sb.append(lastLine.get(0));
for (int i = 1; i < lastLine.size(); ++i) {
sb.append(" ");
sb.append(lastLine.get(i));
}
// add padding
int padding = maxWidth - sb.length();
sb.append(" ".repeat(Math.max(0, padding)));
result.add(sb.toString());
return result;
}
private static void justifyRecursive(int start, String[] words, List<List<String>> outString, List<List<Integer>> outNumSpace, int maxWidth) {
if (start > words.length - 1) {
return;
}
List<String> line = new ArrayList<>();
int i;
int lenMust = 0;
int lenOnlyWords = 0;
for (i = start; i < words.length; ++i) {
String cur = words[i];
if (lenMust + cur.length() > maxWidth) {
--lenMust;
break;
}
line.add(cur);
lenMust += cur.length() + 1;
lenOnlyWords += cur.length();
}
List<String> strings = new ArrayList<>();
List<Integer> numSpaces = new ArrayList<>();
if (line.size() < 2) {
String word = line.get(0);
strings.add(word);
numSpaces.add(maxWidth - word.length());
} else {
int leftWidth = maxWidth - lenOnlyWords;
int leftWidthActual = 0;
int numSpace = leftWidth / (line.size() - 1);
leftWidthActual = numSpace * (line.size() - 1);
strings.add(line.get(0));
for (int j = 1; j < line.size() - 1; ++j) {
String word = line.get(j);
numSpaces.add(numSpace);
strings.add(word);
}
if (leftWidth != leftWidthActual) {
int offset = leftWidth - leftWidthActual;
int j = 0;
while (offset != 0) {
numSpaces.set(j, numSpaces.get(j) + 1);
--offset;
++j;
}
}
numSpaces.add(numSpace);
strings.add(line.get(line.size() - 1));
}
outString.add(strings);
outNumSpace.add(numSpaces);
justifyRecursive(i, words, outString, outNumSpace, maxWidth);
}
}
단어 + 스페이스
가 짝을 이루어야 한다.(줄의 마지막 글자 제외) 그래서 단어 + 스페이스
를 하나의 단위로 보고 줄 안에 들어갈 단어를 판단했다.(한 줄에 들어갈 문자개수(maxWidth) - 총 단어 문자개수의 합) / n - 1 = 단어 사이에 들어갈 white space 개수
- A/
연산은 소수점 뒤에 자리를 버리는 연산이다.do for you ask
이런 줄이 있고, 한줄에 16개의 단어만 들어갈수 있다.(한 줄에 들어갈 문자개수(maxWidth) - 총 단어 문자개수의 합) / n - 1 = 단어 사이에 들어갈 white space 개수
식에 의하면 (16 - 11) 나누기 3 = 1.6666..
이나와서 0.6666..
부분은 버려서 1만 남는다leftWidth
와 leftWidthActual
변수를 두개 사용했다if (leftWidth != leftWidthActual) {
int offset = leftWidth - leftWidthActual;
int j = 0;
while (offset != 0) {
numSpaces.set(j, numSpaces.get(j) + 1);
--offset;
++j;
}
}
// offset distribution을 수행하는 부분
leftWidth
에는 (한 줄에 들어갈 문자개수(maxWidth) - 총 단어 문자개수의 합)
의 결과가 저장되고,leftWidthActual
에는 A * (n - 1)
을 계산한, 실제 A식에 의해서 채워지는 whitespace의 개수를 저장한다.leftWidth
와 leftWidthActual
의 offset 만큼, 왼쪽에 있는 whitespace 부터 1씩 더해서 적용시켜준다leftWidth
> 2 * leftWidthActual
를 반드시 만족하기 때문에 최대 n - 1 번의 offset distribution 을 수행하면 된다List<List<String>> outString, List<List<Integer>> outNumSpace
에 담긴 줄에 들어간느 문자들과, 줄에 들어가는 whitespace 들을 조합해서 justification 이 적용된 배열을 만들어 리턴한다