プログラマー-救命ボート


救命ボート問題リンク

問題の概要


救命ボートで無人島の人を救いたい.
救命ボートは最大1回に2人移動できる.
救命ボートは少なくとも使うべきだ.
救命ボートの重量制限は40キロ~240キロ.
1人あたりの体重は40 kg〜240 kgである.
救命ボートの重量制限はいつも人々の体重の中の最低価格より大きいので、誰も救えない人はいません.
体重の配列と救命ボートの重量制限をパラメータとして与えると、救命ボートの数の最大値を返して、すべての人を救うために必要な救命ボートの数を返す解関数を書きます.

解答方法


O(n)解法


カウント方法(1)


範囲は40~240として指定されているため、配列を使用して範囲の値を計算できます.条件が配列に格納されている値からボートを作成できる場合は、対応するユーザを除外して解決できます.
public class Solution {

    static public int solution(int[] people, int limit) {
        int[] array = new int[241];
        for (int i = 0; i < people.length; i++) {
            array[people[i]]++;
        }
        int answer = 0;
        int person = people.length;
        int nowPoint = 240;

        while (person != 0) {
            if (array[nowPoint] == 0) {
                nowPoint--;
                continue;
            }

            person--;
            array[nowPoint]--;

            answer++;

            for (int i = 240; i >= 40; i--) {
                if (array[i] != 0) {
                    if (i + nowPoint <= limit){
                        person--;
                        array[i]--;
                        break;
                    }
                }
            }

        }

        return answer;
    }
}
  • while(person != 0)従ってO(n)時間的複雑さを有する.
  • O(1)解法


    カウント方法(2)


    40~240の範囲を指定し、配列内の値を使用してカウントし、配列に格納されている値の個数を使用して最大回数240*240を計算します.
    package programmers;
    
    class Solution {
        public int solution(int[] people, int limit) {
    
            int[] array = new int[241];
    
            // 인덱스 값에 넣기
            for (int i = 0; i < people.length; i++) {
                array[people[i]]++;
            }
    
            int answer = 0;
            int firstPoint = limit;
            int secondPoint = 0;
    
            // 경우 판단하기
            while (firstPoint >= 40) {
                // 해당 배열의 개수가 0개라면
                if (array[firstPoint] == 0) {
                    firstPoint--;
                    continue;
                }
    
                // limit + 40보다 더 큰 경우라면
                if (limit - firstPoint < 40) {
                    answer += array[firstPoint];
                    array[firstPoint] = 0;
                    firstPoint--;
                    continue;
                }
    
                // 두번째 탈 사람을 정하기 위함
                // 만약 limit 의 절반 값보다 크다면
                if (limit < firstPoint * 2) {
                    // 두번째 사람은 최대 무게 - 첫번째 탄 사람 무게보다 작아야 한다.
                    secondPoint = limit - firstPoint;
                }
                // 만약 limit 의 절반 값보다 작다면
                else {
                    // 해당하는 값 두개씩 묶어서 값에다 더함.
                    if (array[firstPoint] % 2 == 0) {
                        answer += array[firstPoint] / 2;
                        array[firstPoint] = 0;
                        firstPoint--;
                        continue;
                    } else {
                        answer += array[firstPoint] / 2;
                        array[firstPoint] = 1;
                        secondPoint = firstPoint - 1;
                    }
                }
    
                while (secondPoint >= 40) {
                    if (array[secondPoint] == 0) {
                        secondPoint--;
                        continue;
                    }
    
                    // if 문이 필요한가?
                    if (array[firstPoint] > array[secondPoint]) {
                        answer += array[secondPoint];
                        array[firstPoint] -= array[secondPoint];
                        array[secondPoint] = 0;
                        secondPoint--;
                    } else if (array[firstPoint] < array[secondPoint]) {
                        answer += array[firstPoint];
                        array[secondPoint] -= array[firstPoint];
                        array[firstPoint] = 0;
                        break;
                    } else {
                        answer += array[firstPoint];
                        array[firstPoint] = 0;
                        array[secondPoint] = 0;
                        break;
                    }
    
                }
    
                // secondPoint 을 다 찾아봐도 없다면, 해당하는 배열로 믂어서 더함.
                if (array[firstPoint] != 0) {
                    answer += array[firstPoint];
                    array[firstPoint] = 0;
                }
                firstPoint--;
    
            }
            return answer;
        }
    }
  • 상수 while문従って、O(1)時間的複雑さを有する.
  • 時間の複雑さから大きなメリットを得ることができます.