https://www.acmicpc.net/problem/20210
20210번: 파일 탐색기
첫 줄에 문자열의 개수 N(2 ≤ N ≤ 10,000)이 주어진다. 그 다음 N줄에 정렬할 문자열이 한 줄에 하나씩 주어진다. 모든 문자열의 길이는 100 이하이며, 알파벳 대소문자와 숫자로만 이루어져 있다.
www.acmicpc.net
풀이방법
1. 문자열을 받고 Array.sort 를 변형시킨다.
2. 먼저, 문자열의 길이 중 더 큰 것만큼 for문을 돌리면서 앞 문자or숫자 를 비교한다.
FO, FOO 같이 같다가 한쪽의 비교대상이 사라지는 경우 처리를 해준다. (문자열의 길이 min 값보다 i가 큰경우)
3. 문자를 앞부터 차례대로 비교한다. 경우가 3가지(숫자vs숫자, 숫자vs문자, 문자vs문자)
4. 숫자vs문자
숫자가 우선순위가 높으므로 무조건 숫자가 앞으로 오도록한다.
5. 숫자vs숫자
5-1. 처음에 나오는 0의 개수를 세고, 초반0을 뺀 문자열을 저장한다.
5-2. 문자열을 길이로 비교 한 후, 만약 길이가 같다면 앞부터 하나하나 비교한다.
5-3. 그래도 같다면 0의 개수로 비교한다.(이거까지 같으면 넘어감)
6. 문자vs문자
6-1. 문자가 같다면 패스
6-2. 4가지 경우를 처리해야 한다. (대문자vs대문자, 대문자vs소문자, 소문자vs대문자, 소문자vs소문자)
6-3. 대문자끼리, 소문자끼리 인 경우는 바로 비교해서 넘어갈 수 있다.
6-4. 대문자와 소문자가 같이 있는 경우는 소문자를 대문자로 변경한 후 비교한다. (변경했는데 같다면 기존 대문자였던 문자가 우선순위)
소스코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N;
static String[] str;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
N = Integer.parseInt(br.readLine());
str = new String[N]; //n번째 문자열
for (int i = 0; i < N; i++) {
str[i] = br.readLine();
}
Arrays.sort(str,
(a,b) -> {
//길이 측정
int sizeA = a.length();
int sizeB = b.length();
for (int i = 0; i < Math.max(sizeA, sizeB); i++) {
if(i >= Math.min(sizeA, sizeB)) {
// FO, FOO 일 경우
return Integer.compare(sizeA, sizeB);
}
char curA = a.charAt(i);
char curB = b.charAt(i);
boolean isNumA = isNum(curA);
boolean isNumB = isNum(curB);
/*숫자 vs 문자일 때*/
if(isNumA^isNumB) { //XOR 연산 -> 다르면 참을 반환
//무조건 숫자인 쪽이 앞 -> 숫자(48~57), 문자(65~90 or 97~122)
return Integer.compare(curA, curB);
}
/*숫자 vs 숫자일 때*/
if(isNumA && isNumB) {
//문자나올때까지 keepNum에 저장(0제외), 저장 후 비교
String keepNumA = "";
String keepNumB = "";
int countZeroA = 0;
int countZeroB = 0;
int startPointA = i;
int startPointB = i;
//처음에 나오는 0 개수 카운트
for (int j = i; j < sizeA; j++) {
char c = a.charAt(j);
if(isNum(c)) {
if(c == '0') {
//0개수 카운트
countZeroA++;
startPointA = j+1;
}else {
break;
}
}else {
break;
}
}
//초반 0 빼고 문자열 저장
for (int j = startPointA; j < sizeA; j++) {
char c = a.charAt(j);
if(isNum(c)) {
keepNumA += c;
}else {
break;
}
}
//처음에 나오는 0 개수 카운트
for (int j = i; j < sizeB; j++) {
char c = b.charAt(j);
if(isNum(c)) {
if(c == '0') {
//0개수 카운트
countZeroB++;
startPointB = j+1;
}else {
break;
}
}else {
break;
}
}
for (int j = startPointB; j < sizeB; j++) {
char c = b.charAt(j);
if(isNum(c)) {
keepNumB += c;
}else {
break;
}
}
//앞 0을 다 뺀숫자 -> 길이로 비교, 같으면 하나하나 비교
if(keepNumA.length() != keepNumB.length()) {
return Integer.compare(keepNumA.length(), keepNumB.length());
}
for (int j = 0; j < Math.min(keepNumA.length(), keepNumB.length()); j++) {
if(keepNumA.charAt(j) == keepNumB.charAt(j)) {
continue;
}
return Integer.compare(keepNumA.charAt(j), keepNumB.charAt(j));
}
//앞0의 개수로 비교
if(countZeroA!= countZeroB) {
return Integer.compare(countZeroA, countZeroB);
}
}
/*문자 vs 문자일 때*/
if(!isNumA && !isNumB) {
if(curA == curB) continue; //같으면 패스
//다른경우, 알파벳을 대문자로 바꿔서 비교
boolean isUpperA = isUpper(curA);
boolean isUpperB = isUpper(curB);
if((isUpperA && isUpperB) || (!isUpperA && !isUpperB)) { //둘다 대문자 or 둘다 소문자일 경우
return Integer.compare(curA, curB);
}
if(isUpperA && !isUpperB) { //A가 대문자 && B가 소문자일경우
//B를 대문자로 바꿔서 비교
if(curA == curB-'a' +'A') {
return Integer.compare(curA-1,curB-'a' +'A');
}
return Integer.compare(curA, curB-'a'+'A');
}
if(!isUpperA && isUpperB) { //A가 소문자 && B가 대문자일경우
//A를 대문자로 바꿔서 비교
if(curA-'a' +'A' == curB) {
return Integer.compare(curA-'a' +'A',curB-1);
}
return Integer.compare(curA-'a'+'A', curB);
}
}
}
return 1;
}
);
for (int i = 0; i < N; i++) {
sb.append(str[i]).append("\n");
}
System.out.println(sb.toString());
}
static boolean isUpper(char c) {
if('A'<= c && c<='Z') return true;
return false;
}
static boolean isNum(char c) {
if('0'<=c && c<='9') return true;
return false;
}
}
결과
다시 쳐다보기 싫다.
'Algorithm > java' 카테고리의 다른 글
백준 4195 JAVA : 친구 네트워크 (0) | 2023.05.24 |
---|---|
백준 20543 JAVA : 폭탄 던지는 태영이 (0) | 2023.05.23 |
백준 3687 JAVA : 성냥개비 (0) | 2023.05.23 |
백준 1949 JAVA : 우수 마을 (0) | 2023.04.25 |
백준 16724 JAVA : 피리 부는 사나이 (0) | 2023.04.25 |