모든 자연수 x
에 대해서 현재 값이 x
이면 x
가 짝수일 때는 2로 나누고, x
가 홀수일 때는 3 * x + 1
로 바꾸는 계산을 계속해서 반복하면 언젠가는 반드시 x
가 1이 되는지 묻는 문제를 콜라츠 문제라고 부릅니다.
그리고 위 과정에서 거쳐간 모든 수를 기록한 수열을 콜라츠 수열이라고 부릅니다.
계산 결과 1,000 보다 작거나 같은 수에 대해서는 전부 언젠가 1에 도달한다는 것이 알려져 있습니다.
임의의 1,000 보다 작거나 같은 양의 정수 n
이 주어질 때 초기값이 n
인 콜라츠 수열을 return 하는 solution 함수를 완성해 주세요.
제한사항
import java.util.ArrayList;
class Solution {
public int[] solution(int n) {
ArrayList<Integer> answer = new ArrayList<>();
answer.add(n);
while (n != 1) { // n이 1이 아닌 동안
if (n % 2 == 0) { // n이 짝수면
n /= 2;
} else { // n이 홀수면
n = 3 * n + 1;
}
answer.add(n);
}
return answer.stream().mapToInt(i->i).toArray();
}
}
다른 사람의 코드를 참고 해서 ArrayList를 쓰지 않고도 작성해보았다.
class Solution {
public int[] solution(int n) {
String str = n + " ";
while (n != 1) { // n이 1이 아닌 동안
n = n % 2 == 0 ? n / 2 : 3 * n + 1;
str += n + " ";
}
String[] arr = str.split(" ");
int[] answer = new int[arr.length];
for(int i=0; i<answer.length; i++){
answer[i] = Integer.parseInt(arr[i]);
}
return answer;
}
}
두 코드가 실행시간에서 확연한 차이를 보였다. ArrayList를 사용하는 것이 모든 케이스에서 10ms정도 빠른 속도를 보여줬다.
int[] arr1 = new int[list.size()];
for (int i = 0 ; i < list.size() ; i++ ) {
arr1[i] = list.get(i).intValue();
}
가장 기본적인 방법이다. 반복문을 통해 각 요소별로 접근한다.
int[] arr2 = list.stream()
.mapToInt(i -> i)
.toArray();
int[] arr3 = list.stream()
.mapToInt(Integer :: intValue)
.toArray()
방법 2와 3은 list를 stream으로 변환 후, map을 이용해서 intStream을 가져오고, 그 후에 toArray()를 통해 배열로 만드는 방법이다.
두 방법의 차이는 map 연산 시 int형으로 변경하는 방법의 차이이다.
방법 2 : 자바가 자동으로 각 요소의 Integer 요소를 int형으로 unboxing 해준다. (java 5 이상)
방법 3 : intValue 메서드를 통해 각 요소를 int형으로 변경해준다.
int[] arr4 = list.stream()
.filter(i -> i != null)
.mapToInt(i -> i)
.toArray();
방법 2에 필터를 추가한 것이다. 필터를 통해 null인 요소를 걸러내는 방법이다.