본문 바로가기

Java/알고리즘

[자바 알고리즘 인터뷰] 6장 문자열 처리(3) 로그 파일 재정렬

https://leetcode.com/problems/reorder-data-in-log-files/description/

 

 

- 로그 파일을 재정렬하라. 기준은 다음과 같다. 

 

1) 로그의 가장 앞부분은 식별자로서, 순서에 영향을 끼치지 않는다. 

2) 문자로 구성된 로그가 숫자 로그보다 앞에 오며, 문자 로그는 사전순으로 한다. 

3) 문자가 동일할 경우에는 식별자순으로 한다. 

4) 숫자 로그는 입력 순서대로 한다. 

 

 

풀이 1) 문자 로그와 숫자 로그를 구분해 각각 처리 

 

- 먼저 문자로 구성된 로그가 숫자 로그보다 이전에 오며, 숫자 로그는 입력 순서대로 둔다.

- 문자 로그와 숫자 로그는 서로 정렬 방식이 다르므로, 둘을 분리해 정렬하고 나중에 결과를 서로 이어붙이는 방식으로 풀이 

 

- 먼저 로그에서 각각의 종류를 확인하고 문자 로그라면 문자 리스트에, 숫자 로그라면 숫자 리스트에 삽입 

 

- 문자 로그부터 정렬한다. 

- 문자 로그의 정렬 기준은 사전순으로 하되, 문자가 동일할 경우 식별자순으로 한다 

- 리스트는 Collections를 이용해 다음과 같이 정렬이 가능하다. 

 

Collections.sort(letterlist, new Comparater<String>() {
    @Override
    public int compare(String s1, String s2) {
    	String[] s1x = s1.split(" ",2);
        String[] s2x = s2.split(" ",2);
        
        int compared = s1x[1].compareTo(s2x[1]);
        if(compared == 0) {
        	return s1x[0].compareTo(s2x[0]);
        }else {
        	return compared;
        }
    }
});

 

- Collections.sort()에 Comparator를 이용하면 이처럼 정렬 조건을 설정하고 정렬할 수 있다. 

- 만약 두 값이 동일하다면 0, 비교 대상의 순서가 앞으로 와야 할 경우 1, 비교 대상의 순서가 뒤로 머물러야 할 경우 -1이 된다. 

 

- 식별자와 식별자 외 나머지 부분, 이렇게 두 부분으로 나눈 다음, 식별자 외 나머지 부분의 문자가 동일할 경우에는 문제의 제약 조건에 맞게 그 앞의 식별자끼리 비교하고 결과를 먼저 리턴하도록 처리했다. 

- 이 외에는 식별자 외 나머지 부분의 사전순 정렬이 이뤄질 것이다. 

 

- 자바 8 이상 버전에서는 복잡한 Comparater를 일일이 지정하는 대신 람다 표현식으로 간단히 대체할 수 있다. 

letterlist.sort((s1,s2) -> {
            //식별자와 식별자 외 나머지 부분, 이렇게 두 부분으로 나눈다. 
            String[] s1x = s1.split(" ",2);
            String[] s2x = s2.split(" ",2);

            //문자 로그 사전순 비교
            int compared = s1x[1].compareTo(s2x[1]);

            //문자가 동일할 경우 식별자 비교 
            if(compared == 0)
            {
                return s1x[0].compareTo(s2x[0]);
            }
            else
            {
                //비교 대상의 순서가 동일한 경우 0, 순서가 앞인 경우 1, 순서가 뒤인 경우 -1이 된다. 
                return compared;
            }
        });

 

 

 

class Solution {
    public String[] reorderLogFiles(String[] logs) {
        //문자 로그를 저장할 문자 리스트 
        List<String> letterlist = new ArrayList<>();
        //숫자 로그를 저장할 숫자 리스트
        List<String> digitList = new ArrayList<>();

        for(String log : logs)
        {
            //로그 종류 확인 후 숫자 로그라면 숫자 리스트에 삽입
            if(Character.isDigit(log.split(" ")[1].charAt(0))) {
                digitList.add(log);
            }
            else
            {
                //숫자 로그가 아니라면 문자 리스트에 삽입
                letterlist.add(log);
            }
        }

        //문자 리스트 정렬 진행
        letterlist.sort((s1,s2) -> {
            //식별자와 식별자 외 나머지 부분, 이렇게 두 부분으로 나눈다. 
            String[] s1x = s1.split(" ",2);
            String[] s2x = s2.split(" ",2);

            //문자 로그 사전순 비교
            int compared = s1x[1].compareTo(s2x[1]);

            //문자가 동일할 경우 식별자 비교 
            if(compared == 0)
            {
                return s1x[0].compareTo(s2x[0]);
            }
            else
            {
                //비교 대상의 순서가 동일한 경우 0, 순서가 앞인 경우 1, 순서가 뒤인 경우 -1이 된다. 
                return compared;
            }
        });

        //문자 리스트 뒤로 숫자 리스트를 이어 붙인다. 
        //숫자 로그는 '입력 순서대로'라는 제약 조건이 있으므로 따로 정렬하지 않는다. 
        letterlist.addAll(digitList);

        //리스트를 String 배열로 변환해 리턴한다. 
        return letterlist.toArray(new String[0]);
    }
}

 

실행 시간 : 4밀리초