코딩 테스트

[프로그래머스] (Lv.2) 구명보트 ***

ImKDM 2022. 9. 13. 23:50
728x90

문제


무인도에 갇힌 사람들을 구명보트를 이용하여 구출하려고 합니다. 구명보트는 작아서 한 번에 최대 2명씩 밖에 탈 수 없고, 무게 제한도 있습니다.

예를 들어, 사람들의 몸무게가 [70kg, 50kg, 80kg, 50kg]이고 구명보트의 무게 제한이 100kg이라면 2번째 사람과 4번째 사람은 같이 탈 수 있지만 1번째 사람과 3번째 사람의 무게의 합은 150kg이므로 구명보트의 무게 제한을 초과하여 같이 탈 수 없습니다.

구명보트를 최대한 적게 사용하여 모든 사람을 구출하려고 합니다.

사람들의 몸무게를 담은 배열 people과 구명보트의 무게 제한 limit가 매개변수로 주어질 때, 모든 사람을 구출하기 위해 필요한 구명보트 개수의 최솟값을 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 무인도에 갇힌 사람은 1명 이상 50,000명 이하입니다.
  • 각 사람의 몸무게는 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 40kg 이상 240kg 이하입니다.
  • 구명보트의 무게 제한은 항상 사람들의 몸무게 중 최댓값보다 크게 주어지므로 사람들을 구출할 수 없는 경우는 없습니다.

 

-  출력 예시  -

정답 코드


<  내 정답 코드  1  >      ★   오답    

int total = people.length;
        int idx1 = 0;
        int idx2 = 0;
        
        List<Integer> list = new ArrayList(Arrays.asList(people));
        
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = i; j < list.size() - 2; j++) {
                if (limit - (list.get(i) + list.get(j + 1) < 0) {
                    continue;
                }
                int difMin = limit - (list.get(i) + list.get(j + 1));
                
                if (limit - (list.get(i) + list.get(j + 2)) < difMin) {
                    difMin = limit - (list.get(i) + list.get(j + 2));
                }
            }
                  
                                  
        }
        
        for (int i = 0; i < list.size() - 1; i++) {
            int person = list.get(i);
            dif = limit - person;
            if ()
        }

 

<  내 정답 코드  2  >

class Solution {
    public int solution(int[] people, int limit) {
        Arrays.sort(people);
        int answer = 0;
        
        int left = 0;
        int right = people.length - 1;
        
        while (right >= left) {
            if (people[right--] + people[left] <= limit) {
                left++;
            }
            answer++;
        }
        return answer;
    }
}

 

<  타인 답변 코드  >

class Solution {
    public int solution(int[] people, int limit) {
        Arrays.sort(people);
        
        int i = 0; 
        int j = people.length - 1;
        for (; i < j; --j) {
            if (people[i] + people[j] <= limit)
                ++i;
        }
        return people.length - i;
    }
}

이것을 주의하자!


-  너무 어려웠다. 일단 오답을 보면 ArrayList 를 만들어서 사람들을 하나씩 넣고 한 명씩, 한 명씩 더한 후 limit 에서 뺀 값이 가장 작은 수는 없애기로 했다. 그런데 결국 구현에 실패했다. 너무 복잡했다. 

 

배열을 가지고 풀 수 있다. 일단 "가장 무거운 사람가장 가벼운 사람이 함께 보트를 타지 못할 경우 그 배는 가장 무거운 '한 사람'만 탈 수 있다" 는 전제가 이 문제 풀이의 핵심이다. 이 논제에 도달하면 Arrays.sort( )를 이용해 해당 배열을 가장 가벼운 사람은 왼쪽에, 가장 무거운 사람은 오른쪽으로 정렬한다. 그리고 자체 왼쪽 인덱스, 오른쪽 인덱스 변수를 만들어 오른쪽부터 하나씩 비교해간다. 어짜피 몸무게가 무거운 사람은 배 하나를 차지할테니 right -- 을 해주고, 운이 좋아 가벼운 사람과 탈 수 있으면 왼쪽 인덱스인 left ++ 를 해주어 한 칸 옮긴다. 그렇게 right 변수와 left 변수가 만나는 지점이 모든 사람이 탑승이 완료된 시점이다. 그렇게 카운트를 해주면 문제가 풀린다.

 

-  타인 답변 코드도 동일한 로직이다. 왼쪽, 오른쪽 인덱스를 통해 배열을 탐색한다. 대신 왼쪽 인덱스를 i 로 하고 for 문을 돌린 다음, i 가 늘었을 때가 두 명이서 한 배를 탔기 때문에 마지막은 전체 인원에서 i 만큼 빼준다.