본문 바로가기

Algorithm

프로그래머스 - (Java) 정렬

프로그래머스에 있는 문제 분류별에 있는 정렬 문제를 풀어보았다.

https://github.com/mjung1798/Algorithm/tree/master/algorithm_JAVA/src/com/jyami/programmers/sort

 

mjung1798/Algorithm

My Algorithm Source Code Storage :). Contribute to mjung1798/Algorithm development by creating an account on GitHub.

github.com

이번 정렬문제를 풀면서는 Arrays의 정적 메서드를 많이 사용했다. 사용한 메서드를 하나하나 정리해보자

 

1. Arrays의 정적 메서드 .stream(array)

프로그래머스를 풀다보면 인자로 주어지는 값이 전부 private 타입의 array로 되어있다. 그런데 stream을 많이 쓰는 나로써는 엄청 불편했는데, Arrays 클래스의 정적 메서드를 쓰면 stream을 쉽게 사용할 수 있다.

가장 큰 수 문제를 풀 때 Stream을 이용해서 로직을 수월하게 짤 수 있었다.

public String solution(int[] numbers) {
    StringBuilder sb = new StringBuilder();
    List<String> collect = Arrays.stream(numbers) // Instream
    	.mapToObj(String::valueOf) // stream<String>
        .sorted(new BigComparator()) // stream<String>
        .collect(Collectors.toList()); // List<String>

}

위와 같이 Arrays.stream(object[] array) 를 이용하면 Instream 타입으로 반환된다. 이후 문제의 요구사항에 맞게 내가 원하는 Object 타입으로 변환해주고, .sorted(Comparator) 메소드를 사용하면 쉽게 문제의 로직을 구현 할 수 있다.

다만 염려되는 점은 stream을 사용하면 그냥 for문으로 구현했을 때보다 프로그램 실행시간이 더 오래 걸린다고 하는데, 아직 확인은 안해본 상태다.

내 생각에는 stream 을 사용하는 경우에는 빠르게 로직 구현이 가능하지만, 가장 중요한건 input parameter와 return 타입을 맞추는 것이라고 생각한다. 그런 의미에서 만약 intellij 등의 툴을 사용하지 못하는 코딩테스트에서 stream 메서드를 잘 모른다면 오히려 더 시간을 많이 잡아먹을 수 있다는 점을 생각하자.

 

2. Arrays의 정적 메서드 .toString(array)

나는 프로그래머스로 문제를 풀 때 주어지는 Solution class를 inner class로 만들고, main을 이용해서 디버깅 하면서 풀곤 한다. 그래서 array의 같은 경우는 테스트 결과가 맞는지 확인하곤 하는데 그때 배열 값을 그냥 프린트하면 해시값이 나와서 for문을 그때그때 만들어야 했다.

int[] solution = {3,4,5,2};
System.out.println(Arrays.toString(solution));

따라서 반환된 private array 값을 확인할 땐 다음과 같이 Arrays.toString(object[] array) 를 사용해서 출력값을 확인한다.

 

3. Arrays의 정적 메서드 .sort(array)

이전 글에서 언급한 comparable을 이용한 Collections.sort() 혹은 comparator를 이용한 List<Object>.sort() 같은 경우에는 전부 Object타입에 대한 sort 메서드이다. int, double 등의 primitive 타입은 전부 wrapper 클래스인 Integer, Double로 변환해주고 나서 사용해야한다. 

그래서 primitive 타입일때 기본적인 sort는 Arrays.sort() 를 이용할 수 있다.

int[] result = {1,6,3,5,8};
Arrays.sort(result);

물론 primitive 타입이 아닌 Object 역시 정렬이 가능하며, 이 경우에는 comparator를 추가할 수도 있다.

 class Alphabet {
 	int number;
 	char letter;

	public Alphabet(int number, char letter) {
		this.number = number;
		this.letter = letter;
	}
}

만약 위와 같은 Alphabet 객체가 있다고 가정하자.

Alphabet[] alphabets = {new Alphabet(1, 'a'), new Alphabet(2, 'b')};
Arrays.sort(alphabets);
Arrays.sort(alphabets, Comparator.comparingInt(o -> o.number));

Arrays.sort(Object[] objects); 라는 메서드가 있긴하지만 이렇게 사용했을 경우에는 ClassCastException 이 발생한다. 즉, Arrays.sort(Object[] object); 메서드는 Integer, Boolean, Double 과 같은 Wrapper 타입을 정렬할 때 사용한다.

따라서 위와 같이 멤버를 임의로 정의한 클래스의 경우에 Arrays.sort() 를 사용하려면 새로운 Comparator를 정의해주어야하고, 위 코드에서는 간단하게 number 멤버로 비교하는 Comparator로 비교하라고 지정해주었다.

 

4. Arrays의 정적 메서드 .copyOfRange(array) .copyOf(array)

내가 지정한 배열의 깊은복사를 가능하게 해주는 메서드이다.

int[] array = {1, 5, 2, 6, 3, 7, 4};
int[] array2 = Arrays.copyOf(array, 4); // {1,5,2,6}
int[] array3 = Arrays.copyOfRange(array, 3, 5); // {6,3}

copyOf(object[] array, int newLength)는 새로 지정해주는 길이만큼의 array를 만들어 주며, 기존의 array보다 newLength 가 작은 경우엔, 해당하는 길이 만큼만 배열을 만들어준다.
copyOfRange(object[] array, int from, int to)는 지정한 인덱스에 해당하는 곳만 copy 해준다. 이때 주의할 점은 from의 인덱스는 포함되지만 to의 인덱스는 포함되지 않는다. 즉 [from, to) 에 해당하는 인덱스만큼만 배열의 깊은 복사가 이루어진다.