알고리즘

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

jaewoo 2023. 2. 4. 13:18

 

 

문제

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

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

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

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

 

제한사항

 

 

배열에서 두 개의 값을 더하여 sum을 만든다 -> 투포인터 느낌을 받았다. 

 

푸는 순서

- 배열을 오름차순으로 정렬해야한다. (내림차순으로도 가능)

- count, left(배열의 시작), right(배열의 끝) 선언

- while(left < right)  -> 투포인터로 하나씩 맞춘다.

- 만약 limit(제한무게) 보다 클 경우 right(큰 값)을 혼자 태우고 right만 왼쪽으로 움직인다.

- 제한무게보다 작을 경우 right(큰 값) left(작은 값) 을 같이 태우고 둘 다 이동한다.

- 순회할때 마다 배는 항상 태워야 하기에 if문으로 둘 다 이동할지 한 쪽만 이동할지를 정한다.

- while문에서 만약 right만 이동시켜 혼자 태울 경우 left가 타는 배의 개수가 count에 포함되지 않는다. 그래서 마지막에 if문을 통해 left == right 일 경우 1을 증가시켰다.

 

import java.util.*;

class Solution {
    public int solution(int[] people, int limit) {
        int answer = 0;
       
        Arrays.sort(people);
        
        int count= 0;
        int left = 0;
        int right = people.length - 1;
        
        while(left < right){
            int sum = people[left] + people[right];
            
            if(sum > limit){    //같이 못탐 패스 왼쪽편 한명만 먼저 태움
                right--;
            }else{ //같거나 작은 경우 같이 탐 그래서 둘 다 이동
                left++;
                right--;
            }
            count++;    //카운트 한번 올리면서 무게가 같거나 작으면 같이 아니면 혼자
        }
        if(left == right){
            count++;
        }
        
        
        return count;
    }
}

 

 

내림차순으로 했을경우

package com.example.algorithgm.greedy;

import java.util.Arrays;

public class Boat {

    public static void main(String[] args) {
        System.out.println(solution(new int[]{70,50,80},100));;
    }

    public static int solution(int[] people,int limit){ //사람의 몸무게 배열, 보트에 제한

            Integer[] arr = Arrays.stream(people).boxed().toArray(Integer[]::new);  //내림차순으로 하기 위해 Integer배열변환

            Arrays.sort(arr, (o1,o2) -> o2-o1); //오름차순으로 변경

            int left = 0;   //주어진 배열의 시작
            int right = arr.length - 1; //주어진 배열에 오른쪽 맨 끝
            int count = 0;

            while(left < right){
                    int sum = arr[left] + arr[right];

                    if(sum > limit){    //제한된 무게를 초과할 경우 혼자 타야하므로 가장 큰 놈을 태운다.
                        left++;
                    }else{  //제한된 무게를 초과하지 않았기에 큰 놈과 작은 놈을 같이 태운다.
                        left++;
                        right--;
                    }
                    count++;    //한 배에 큰 놈 한명 태울지, 작은 놈 큰 놈 같이 태울지 정한다.
            }
            if(left == right){  //left와 right가 같다는 뜻은 while문 마지막에 큰 놈 작은 놈 따로 태운다는 뜻인데
                count++;        //큰 놈 혼자 태우고 작은 놈은 배룰 태우지만 개수를 세지 않음 그렇기에 여기서 개수를 체크한다.
            }                   //반대로 둘이 합쳐 limit을 넘지 않는다면 한 배에 탄 것이므로 체크를 안 해도 됨(이럴 경우 left , rigiht는 다름)
            return count;
    }
}

 

Arrays.sort()에 Comparater를 사용하려면 int 배열이 아닌 Integer 배열로 해야한다. 그래서 boxed()로 배열 타입을 변경시키고 해야한다.