일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- mysql
- jsp
- mst
- 웹 프로그래밍
- BJ
- SERVLET
- 크루스칼 알고리즘
- 부스트코스
- 웹서버
- request
- 네이버 부스트캠프 ai tech
- 다이나믹 프로그래밍
- 웹프로그래밍
- 소수
- DP
- 해시
- 그리디
- 프림 알고리즘
- dbms
- Kruskal's Algorithm
- 백준
- programmers
- 프로그래머스
- 벡엔드
- 순열 알고리즘
- 정렬 알고리즘
- 정렬
- greedy
- Prim's Algorithm
- 브라우저
- Today
- Total
끵뀐꿩긘의 여러가지
프로그래머스 - 구명보트 (sol.java) 본문
◎문제 링크
programmers.co.kr/learn/courses/30/lessons/42885?language=java#
코딩테스트 연습 - 구명보트
무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다. 예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 5
programmers.co.kr
◎문제 파악
문제의 조건:
1. 구명보트는 한 번에 최대 2명까지만 탈 수 있다.
2. limit보다 무거운 사람들이 보트를 탈 수 없다. ex) 70kg랑 80kg의 사람은 100kg이 limit인 보트에 탈 수 없다.
◎첫 코드
public int solution(int[] people, int limit) {
int answer = 0;
ArrayList<Integer> person = new ArrayList<>();
//신축성이 없는 배열보다는 ArrayList가 효율적일 것 같다.
for(int i = 0; i<people.length; i++){
person.add(people[i]);
} //ArrayList에 배열 people을 넣는다
Collections.sort(person); //ArrayList 정렬
while(!person.isEmpty()){
answer++;
int i = person.remove(0);
for(int p = person.size()-1; p>=0; p--){
if(i+person.get(p)<=limit){
person.remove(p);
break;
}
}
}
return answer;
}
코드 동작 예시
1. people을 정렬한다
people | 30 | 40 | 70 | 80 |
2. index 0 요소를 remove하고, index 0의 값과 합쳐 limit보다 작은 값을 뒤에서부터 탐색한다.
people | 40 | 70 | 80 |
3. 70이 30과 합쳐서 100이므로 함께 삭제한다
people | 40 | 80 |
4. index 0 요소를 remove하고, index 0의 값과 합쳐 limit보다 작은 값을 뒤에서부터 탐색한다.
people | 80 |
5. 40과 합쳐서 100이하인 요소가 없다.
6. index 0 요소를 remove하고, index 0의 값과 합쳐 limit보다 작은 값을 뒤에서부터 탐색한다.
people |
이렇게 작동하는 코드를 짜니, 효율성 테스트에서 모두 시간이 초과 되었다.
◎코드 개선
1. 내림차순 정렬하면 (즉, 맨 뒤에 요소를 제일 먼저 살펴보면)
"index 0의 값과 합쳐 limit보다 작은 값을 뒤에서부터 탐색한다."의 과정이 생략된다.
ex) [20,80,90] limit = 100일 경우
20부터 쳐다보면 20+90>=100인지, 20+80>=100 인지 살펴보아야 하지만,
90부터 쳐다보면 90+20>100이므로, 20 다음의 숫자도 100을 넘을 것이라는 것을 알 수 있다.
2. limit/2 보다 작은 값이 나오면, 그 인덱스부터는 무조건 2명씩 보낼 수 있다.
ex) [20,20,20,20,20,80] limit = 100일 경우
1. 80과 20이 사라지고, [20,20,20,20] 이 남는다
2. 이때 맨 끝 인덱스의 값 20 < 100/2이고, 20 앞 값들은 모두 20보다 작거나 같으므로,
남은 4명을 무조건 2명씩 태워서 보낼 수 있다.
3. ArrayList 쓰지 않기
배열을 ArrayList에 넣은 과정은 시간 복잡도 Olog(n)을 가지므로, 필요 없을 경우에는 쓰지 않는 게 옳다.
개선한 코드:
public int solution(int[] people, int limit) {
int answer = 0;
Arrays.sort(people); //배열 정렬, ArrayList 사용x
//ArrayList를 사용하지 않았으므로, 탐색할 부분을 정해주는 변수 k와 j 도입
int k = people.length-1;
int j = 0;
while(k>=j){
int i = people[k]; //뒤에서부터 살펴보기
if(i<=limit/2){
//어떤 값이 limit/2보다 작거나 같으면 그 값부터는 무조건 2명씩 보낼 수 있음
if((k-j+1) % 2==0){
answer = answer + (k-j+1)/2;
}else{
answer = answer + (k-j+1)/2+1;
}
break;
}
k--;
answer++;
if(k>=j && people[j]+i<=limit){
j++;
}
}
return answer;
}
코드를 개선하니, 다행히 효율성 테스트를 통과하였다.
불필요한 반복을 줄이고, 현 상황에 가장 잘 맞는 자료구조를 쓰는 것이 얼마나 중요한지 알게 되었다.
◎ 다른 사람의 풀이
import java.util.Arrays;
class Solution {
public int solution(int[] people, int limit) {
Arrays.sort(people);
int i = 0, j = people.length - 1;
for (; i < j; --j) {
if (people[i] + people[j] <= limit)
++i;
}
return people.length - i; //전체 사람의 수 - 두명이서 탄 횟수 = 보트의 개수
}
}
엄청 깔끔하고 효율적이다.. 코드 잘 짜는 사람들이 이렇게 많구나 싶다.
'JAVA > 문제풀이 - 프로그래머스' 카테고리의 다른 글
프로그래머스 - 단속카메라 (sol.java) (0) | 2021.05.26 |
---|---|
프로그래머스 - 섬 연결하기 (sol.java) (0) | 2021.05.24 |
프로그래머스 - 소수찾기 (sol.java) (0) | 2021.04.27 |
프로그래머스 - 큰 수 만들기 (sol.java) (0) | 2021.04.26 |
프로그래머스 - 조이스틱 (sol.java) (0) | 2021.04.26 |