Algorithm

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

프로그래머스에 있는 문제 분류별에 있는 정렬 문제를 풀어보았다.https://github.com/mjung1798/Algorithm/tree/master/algorithm_JAVA/src/com/jyami/programmers/sort mjung1798/AlgorithmMy Algorithm Source Code Storage :). Contribute to mjung1798/Algorithm development by creating an account on GitHub.github.com이번 정렬문제를 풀면서는 Arrays의 정적 메서드를 많이 사용했다. 사용한 메서드를 하나하나 정리해보자 1. Arrays의 정적 메서드 .stream(array)프로그래머스를 풀다보면 인자로 주어지는 값이 전부 pr..

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

728x90

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

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) 에 해당하는 인덱스만큼만 배열의 깊은 복사가 이루어진다.

I solved the sorting problems from the category section on Programmers.

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

While solving these sorting problems, I used a lot of static methods from the Arrays class. Let me go through each method I used one by one.

 

1. Arrays Static Method .stream(array)

When solving problems on Programmers, the arguments are all given as primitive type arrays. As someone who uses streams a lot, this was really inconvenient, but using the static methods of the Arrays class makes it easy to work with streams.

When solving the "Largest Number" problem, I was able to write the logic smoothly using 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>

}

As shown above, using Arrays.stream(object[] array) returns an IntStream type. After that, you can convert it to whatever Object type you need according to the problem requirements, and use the .sorted(Comparator) method to easily implement the problem's logic.

One concern, though, is that using streams supposedly takes longer to execute than implementing it with a plain for loop, but I haven't verified this myself yet.

In my opinion, using streams makes it possible to implement logic quickly, but the most important thing is matching the input parameter and return types. With that in mind, if you're taking a coding test where you can't use tools like IntelliJ and you're not familiar with stream methods, it could actually end up eating more of your time.

 

2. Arrays Static Method .toString(array)

When I solve problems on Programmers, I make the given Solution class an inner class and debug using the main method. So for arrays, I often check whether the test results are correct, but when you just print an array directly, it outputs the hash value, so I had to write a for loop every time.

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

So when I want to check the returned primitive array values, I use Arrays.toString(object[] array) like above to verify the output.

 

3. Arrays Static Method .sort(array)

The Collections.sort() using Comparable and List<Object>.sort() using Comparator that I mentioned in a previous post are all sort methods for Object types. Primitive types like int and double all need to be converted to their wrapper classes like Integer and Double before you can use them.

So for primitive types, you can use Arrays.sort() for basic sorting.

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

Of course, you can also sort Objects (not just primitive types), and in that case, you can add a Comparator as well.

 class Alphabet {
 	int number;
 	char letter;

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

Let's say there's an Alphabet object like the one above.

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

There is a method called Arrays.sort(Object[] objects);, but using it like this will throw a ClassCastException. In other words, the Arrays.sort(Object[] object); method is meant for sorting Wrapper types like Integer, Boolean, and Double.

So for classes with custom-defined members like the one above, if you want to use Arrays.sort(), you need to define a new Comparator. In the code above, I simply specified a Comparator that compares by the number member.

 

4. Arrays Static Methods .copyOfRange(array) and .copyOf(array)

These are methods that allow you to perform a deep copy of a specified 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) creates a new array with the specified length. If newLength is smaller than the original array, it creates an array with only that many elements.
copyOfRange(object[] array, int from, int to) copies only the portion corresponding to the specified indices. Note that the from index is inclusive but the to index is exclusive. In other words, only the elements in the range [from, to) are deep copied into the new array.

댓글

Comments