CS/자료구조&알고리즘

[프로그래머스] 파일명 정렬 : JAVA

봄의 개발자 2024. 1. 11.
728x90
반응형

 

 

초기 제출 코드

import java.util.*;

class Solution {
    public String[] solution(String[] files) {
        Arrays.sort(files, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                FileName fileName1 = exportFileName(s1);
                FileName fileName2 = exportFileName(s2);
                
                if (fileName1.getHead().toLowerCase().compareTo(fileName2.getHead().toLowerCase()) > 0) {
                    return 1;
                } else if (fileName1.getHead().toLowerCase().compareTo(fileName2.getHead().toLowerCase()) == 0) {
                    int num1 = Integer.parseInt(fileName1.getNumber());
                    int num2 = Integer.parseInt(fileName2.getNumber());
                    
                    if (num1 == num2) {
                        return 0;
                    } else {
                        return num1 - num2;
                    }
                    
                } else {
                    return -1;
                }
                
            }
        });
        
        return files;
    }
    
    private FileName exportFileName(String fileName) {
        
        int numberStartIdx = 0;
        for (int i = 0; i < fileName.length(); i++) {
            if (fileName.charAt(i) >= 48 && fileName.charAt(i) <= 57) {
                numberStartIdx = i;
                break;
            }
        }
        
        int numberEndIdx = 0;
        for (int i = numberStartIdx; i < fileName.length(); i++) {
            if (fileName.charAt(i) < 48 || fileName.charAt(i) > 57) {
                numberEndIdx = i;
                break;
            } 
        }
        
        return new FileName(fileName.substring(0, numberStartIdx), 
                            fileName.substring(numberStartIdx, numberEndIdx),
                            fileName.substring(numberEndIdx + 1, fileName.length()));
    }
    
    public class FileName {
        private String head;
        private String number;
        private String tail;
        
        public FileName(String head, String number, String tail) {
            this.head = head;
            this.number = number;
            this.tail = tail;
        }
        
        public String getHead() {return this.head;}
        public String getNumber() {return this.number;}
        public String getTail() {return this.tail;}
    }
}

 

여기서 런타임 에러가 발생해서 25/100점을 받고 틀렸었다. 이 문제는 'numberStartIdx'가 'numberEndIdx'와 동일한 경우, 즉 파일 이름에 숫자 부분이 없는 경우와 관련이 있을 수 있습니다. 이러한 경우 fileName.substring(numberStartIdx, numberEndIdx)는 빈 문자열이 되어 이를 정수로 구문 분석하려고 할 때 NumberFormatException이 발생되는 것으로 추측된다.

 

이를 해결하기 위해

  1. 문자가 숫자인지 확인하기 위해 Character.isDigit 를 사용했다.
  2. 숫자 부분이 없는 경우를 고려해 numberEndIdx를 구하는 부분을 수정했다.

 

최종 제출 코드

import java.util.Arrays;
import java.util.Comparator;

class Solution {
    public String[] solution(String[] files) {
        Arrays.sort(files, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                FileName fileName1 = exportFileName(s1);
                FileName fileName2 = exportFileName(s2);

                int headComparison = fileName1.getHead().toLowerCase().compareTo(fileName2.getHead().toLowerCase());

                if (headComparison != 0) {
                    return headComparison;
                }

                int num1 = Integer.parseInt(fileName1.getNumber());
                int num2 = Integer.parseInt(fileName2.getNumber());

                return Integer.compare(num1, num2);
            }
        });

        return files;
    }

    private FileName exportFileName(String fileName) {
        int numberStartIdx = 0;
        for (int i = 0; i < fileName.length(); i++) {
            if (Character.isDigit(fileName.charAt(i))) {
                numberStartIdx = i;
                break;
            }
        }

        int numberEndIdx = fileName.length();
        for (int i = numberStartIdx; i < fileName.length(); i++) {
            if (!Character.isDigit(fileName.charAt(i))) {
                numberEndIdx = i;
                break;
            }
        }

        return new FileName(
                fileName.substring(0, numberStartIdx),
                fileName.substring(numberStartIdx, numberEndIdx),
                fileName.substring(numberEndIdx));
    }

    public class FileName {
        private String head;
        private String number;
        private String tail;

        public FileName(String head, String number, String tail) {
            this.head = head;
            this.number = number;
            this.tail = tail;
        }

        public String getHead() {
            return this.head;
        }

        public String getNumber() {
            return this.number;
        }

        public String getTail() {
            return this.tail;
        }
    }
}

 

통과!

 

문제 풀이

  1. Head, Number, Tail을 구분해서 관리하기 위해 객체 클래스를 생성한다.
  2. 세가지를 활용해 정렬 조건을 구현한다.
  3. Head는 문자로만 표현 가능한데, 이 Head가 정렬 기준에서 우선순위가 가장 크다. 이때 주의해야할 것은 대/소문자 구분을 하지 않는 것이다. 그래서 toLowerCase()를 사용해서 비교할 때 모두 소문자로 바꿨다.
  4. 만약 Head가 같다면 정렬 기준에서 두번째로 우선순위가 큰 Number을 통해 비교한다. 이때 011, 11은 동일한 숫자로 취급한다. 
    String str = "011";
    System.out.println(Integer.parseInt(str));
    -> 이 결과가 11이기 때문에 String -> Integer로 형변환을 통해 Number 비교를 했다. 
  5. Number도 동일하다면 이땐 저장된 순서 그대로 유지하는 것이다.
728x90
반응형

댓글