정렬을 잘 응용할 수 있는 지 확인할 수 있는 문제였다.
핵심 알고리즘인 정렬을 구현하는 데에는 1분도 걸리지 않았는데, 문자열을 파싱할 때 인덱스 찾는 데에서 오류가 계속 나서 디버깅하느라 시간이 좀 걸렸다. 그치만 풀어내서 참 뿌듯하다.
parseFiles()
: 주어진 files
를 FileName
리스트로 파싱한다.getStartAndEndIndexOfNumber()
: file
에서 첫 번째로 등장하는 숫자의 시작과 끝 인덱스를 알아낸다.number
의 길이는 5를 초과할 수 없기에 이 조건에 따라 endOfNumber
를 조정한다.head
, number
, tail
을 파싱한다.FileName
객체를 생성하고 리스트에 저장한다.sort()
: FileName
클래스의 compareTo()
를 통해 FileName
리스트를 주어진 조건대로 정렬한다.head
를 알파벳 순으로 정렬할 때는 String 클래스의 compareToIgnoreCase()
를 사용한다.number
를 정렬할 때는 Integer 클래스의 compare()
를 사용한다.import java.util.*;
class Solution {
private static final int START = 0;
private static final int END = 1;
public String[] solution(String[] files) {
List<FileName> result = parseFiles(files);
result.sort(FileName::compareTo);
return buildStringArray(result);
}
private List<FileName> parseFiles(String[] files) {
List<FileName> result = new ArrayList<>();
for (String file : files) {
int[] indexOfNumber = getStartAndEndIndexOfNumber(file);
String head = file.substring(0, indexOfNumber[START]);
String number = file.substring(indexOfNumber[START], indexOfNumber[END] + 1);
String tail = parseTail(file, indexOfNumber[END] + 1);
FileName fileName = new FileName(head, number, tail);
result.add(fileName);
}
return result;
}
private int[] getStartAndEndIndexOfNumber(String file) {
boolean isCurrentCharNumber = false;
int startOfNumber = 0, endOfNumber = 0;
for (int i = 0; i < file.length(); i++) {
if (file.charAt(i) >= '0' && file.charAt(i) <= '9') {
if (!isCurrentCharNumber) {
startOfNumber = i;
isCurrentCharNumber = true;
}
} else {
if (isCurrentCharNumber) {
endOfNumber = i - 1;
break;
}
}
}
if (endOfNumber == 0) endOfNumber = file.length() - 1;
if (isNumberLongerThanLimit(startOfNumber, endOfNumber)) endOfNumber = startOfNumber + 4;
return new int[]{startOfNumber, endOfNumber};
}
private boolean isNumberLongerThanLimit(int startOfNumber, int endOfNumber) {
return endOfNumber - startOfNumber > 4;
}
private String parseTail(String file, int startIndex) {
if (startIndex < file.length()) return file.substring(startIndex);
else return "";
}
private String[] buildStringArray(List<FileName> sortedFiles) {
String[] result = new String[sortedFiles.size()];
for (int i = 0; i < sortedFiles.size(); i++)
result[i] = sortedFiles.get(i).fileName();
return result;
}
}
class FileName {
String head;
String number;
String tail;
int numberValue;
public FileName(String head, String number, String tail) {
this.head = head;
this.number = number;
this.tail = tail;
this.numberValue = Integer.parseInt(number);
}
public String fileName() {
return head + number + tail;
}
public static int compareTo(FileName o1, FileName o2) {
if (o1.head.compareToIgnoreCase(o2.head) == 0)
return Integer.compare(o1.numberValue, o2.numberValue);
else
return o1.head.compareToIgnoreCase(o2.head);
}
}