문제를 풀다가 배열에서 원하는 값만 추출해내고 싶은데 원하는 값이 아닌 값이 있던 자리에 null값이 계속 나와서 없애는 방법을 풀어보고 정리해보고자 한다.
출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
문제설명
오늘 해야 할 일이 담긴 문자열 배열 todo_list와 각각의 일을 지금 마쳤는지를 나타내는 boolean 배열 finished가 매개변수로 주어질 때, todo_list에서 아직 마치지 못한 일들을 순서대로 담은 문자열 배열을 return 하는 solution 함수를 작성해 주세요.
제한사항
- 1 ≤ todo_list의 길이 1 ≤ 100
- 2 ≤ todo_list의 원소의 길이 ≤ 20
- todo_list의 원소는 영소문자로만 이루어져 있습니다.
- todo_list의 원소는 모두 서로 다릅니다.
- finished[i]는 true 또는 false이고 true는 todo_list[i]를 마쳤음을, false는 아직 마치지 못했음을 나타냅니다.
- 아직 마치지 못한 일이 적어도 하나 있습니다.
입출력 예
입출력 예 #1
- 예제 1번의 todo_list 중에서 "problemsolving"과 "swim"은 마쳤고, "practiceguitar"와 "studygraph"는 아직 마치지 못했으므로 todo_list에서 나온 순서대로 담은 문자열 배열 ["practiceguitar", "studygraph"]를 return 합니다.
문제풀이
정답 작성코드
class Solution {
public String[] solution(String[] todo_list, boolean[] finished) {
//finished에서 false인 값 구하기
int falseCnt = 0;
for(boolean f : finished){
if(!f){
falseCnt++;
}
}
//결과 배열 초기화
String[] answer = new String[falseCnt];
//결과 배열에 false 값 복사
int answerIdx = 0;
for(int i=0; i<todo_list.length; i++){
if(!finished[i]){
answer[answerIdx] = todo_list[i];
answerIdx++;
}
}
return answer;
}
}
1. 먼저 boolean 매열인 finished에서 false인 값의 개수를 구했다. 이것은 새로 만든 String배열의 길이로 사용할 것이다.
2. 결과값을 넣어줄 배열을 초기화 시켰다. 이때의 길이는 1번에서 구했던 값이 된다.
3. 결과 배열에 false값을 가지는 todo_list 배열의 값만을 2번에서 초기화한 배열에 차례로 넣어준 후 반환한다.
처음에 작성한 것이 틀렸던 이유
내가 처음에 작성했던 코드는 아래와 같다.
class Solution {
public String[] solution(String[] todo_list, boolean[] finished) {
String[] answer = new String[todo_list.length];
for(int i=0; i<todo_list.length; i++){
if(finished[i]==false){
answer[i] = todo_list[i];
}
}
return answer;
}
}
테스트 결과 다음과 같은 결과가 반환되었다.
answer로 반환된 배열의 값에 false가 아닌 true인 값에는 null값이 들어 간 것을 볼 수 있다.
여기서 두가지가 틀린 것을 볼 수 있었는데 첫번째는 길이가 틀렸다는 것과 두번째는 null값이 들어가면 안되는데 들어갔다는 것이었다.
따라서 이 두 가지를 없애는 코드를 추가적으로 작성할 필요가 있었다.
1. 그래서 먼저 `finished` 배열에서 false인 값의 개수를 구하였다. 그렇게 해서 결과 배열 `answer`의 크기를 동적으로 조정하지 않고 `falseCnt`로 설정하였다.
2. 그리고 `answerIdx`를 새로 초기화 선언하여 결과 배열 `answer`에 아직 마치지 못한 일을 복사할 때에는 `answerIdx`를 사용하여 값을 대입하도록 하였다.
이렇게 한 이유는 결과배열 `answer`에 값을 복사할 때, 원본 배열인 `todo_list` 배열의 인덱스와 결과배열의 인덱스가 일치하지 않을 수 있기 때문이다.
내가 처음 작성했던 코드에서는 결과 배열의 크기를 `todo_list` 배열과 동일하게 설정하고, 아직 마치지 못한 일에 해당하는 위치에만 값을 복사하려고 했지만 결과 배열의 크기와 `todo_list`배열의 크기가 달라 null 비워진 위치에는 null값이 들어갔다.
하지만 새로 작성한 코드에서는 `falseCnt`를 이용하여 결과배열의 크기를 결정하고 `answerIdx`를 사용하여 결과 배열에 값을 복사한다. 이렇게 함으로써 결과 배열의 크기와 아직 마치지 못한 일들의 개수가 일치하도록 보장하는 것이다. 그런 다음에 `answerIdx`를 이용하여 결과 배열에 값을 복사하기 때문에 아직 마치지 못한 일(false를 가지는 값)이 중간에 위치해도 결과배열에서는 null값 없이 차례로 원하는 값을 복사해 넣을 수 있는 것이다.
결론은, 결과 배열의 크기와 원본 배열의 크기가 다른 경우 생기는 문제를 예방하기 위해서는 결과배열에 새로운 index를 선언하여 이용하는 것이 좋다.
'Language > Java 예제 정리' 카테고리의 다른 글
[Java] 정수 오버플로우로 인한 반환값 다름정리 - (프로그래머스 12943 콜라츠 추측) (1) | 2023.10.23 |
---|