programmers. 구명보트
남들은 다 쉽게 푸는것 같은데 저는 왜 이렇게 그리디 문제가 감이 안올까요..
처음엔 우선순위큐를 사용하여 가장 작은 몸무게를 찾은 다음 남은 사람들 중 무게제한을 초과하지 않는 사람들 중 가장 무거운 사람을 골랐습니다. 아무래도 남은 사람들 중 가장 무거운 사람을 찾는 과정에서 복잡도가 증가하였고 여러 테스트케이스에서 통과하지 못하였습니다.
이렇게 제일 큰 것 찾고 가장 작은 것도 동시에 찾기 위해선 우선순위큐 대신 리스트를 사용하고 포인터를 2개를 사용하면 됩니다(다 풀고나서 다른 사람들의 풀이를 보니 Deque
도 많이 사용했더라구요. 어차피 똑같은 맥락이죠). 리스트를 오름차순 정렬하고 가장 작은(왼쪽) 수의 인덱스를 왼쪽(left
), 가장 큰(오른쪽) 수의 인덱스를 오른쪽(right
)에 두고 while(left < right)
인 경우엔 한해 계속 반복하는 것입니다.
여기서 포인트는 가장 작은 수와 가장 큰 수가 짝이 될때 가장 효율적이라는 점(문제에서 최대 2명 밖에 탈 수 없다고 가정)입니다. 혼자 타는 경우가 있는데요. left
수와 right
수의 합이 무게제한을 넘을 때이겠죠. 이때는 right
만 조용히 -1 해줍니다. 만약 left
수와 right
수의 합이 무게제한을 안 넘을 때는 환상의 짝궁인 것입니다. 이때는 count
를 +1 해주고 다음 경우를 위해 left++
, right--
을 해줍니다. 그렇게 하여 마지막 답은 people.length() - count
인데요. 그 이유는 환상의 짝궁이 된 수는 지워야 딱 나오거든요. 조금만 생각해보면 알 것입니다.
class Solution {
public int solution(int[] people, int limit) {
List<Integer> list = new ArrayList();
for (int person : people) {
list.add(person);
}
Collections.sort(list);
int left = 0;
int right = list.size() - 1;
int count = 0;
while(left < right) {
if(list.get(left) + list.get(right) <= limit) {
count++;
left++;
right--;
} else {
right--;
}
}
return people.length - count;
}
}
위 코드는 이 블로그를 참고하여 작성되었습니다. 작은 수와 큰 수를 동시에 알아야할 때 정렬 후 포인터를 2개를 동시에 사용 또는 Deque를 사용할 수 있다는 생각을 못했네요.. 다음엔 잘 활용할 수 있기를...!
'Algorithm > problem solving' 카테고리의 다른 글
Today's Algorithm(2019-01-03) (0) | 2019.01.04 |
---|---|
Today's Algorithm(2019-01-02) (0) | 2019.01.02 |
Today's Algorithm(2018-12-31) (1) | 2018.12.31 |
Today's Algorithm(2018-12-30) (0) | 2018.12.30 |
Today's Algorithm(2018-12-29) (0) | 2018.12.30 |