잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→

현록의 기록저장소

[Lv1] 체육복 본문

Problem Solving/programmers

[Lv1] 체육복

현록 2019. 4. 10. 19:33

https://programmers.co.kr/learn/challenges

 

프로그래밍 강의 | 프로그래머스

기초부터 차근차근, 직접 코드를 작성해 보세요.

programmers.co.kr

문제 설명

 

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 전체 학생의 수는 2명 이상 30명 이하입니다.
  • 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
  • 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

입출력 예

n lost reverse return
5 [2, 4] [1, 3, 5] 5
5 [2, 4] [3] 4
3 [3] [1] 2

입출력 예 설명

예제 #1
1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.

예제 #2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.

 

문제 원출처: http://hsin.hr/coci/archive/2009_2010/contest6_tasks.pdf

 


총 학생수가 n명.

여벌 옷을 가진 학생들이 reverse에 나오고,

잃어버린 학생들은 lost에 나옴. 여벌옷을 가져왔더라도 잃어버리면 모두 잃어버림.

체격상 자기 번호의 앞 뒤 사람에게만 여벌옷을 빌려줄 수 있음.

즉, 1명에게서만 받을 수도 있지만 2명에게서 받을 수 있는 사람도 있음.

 

LinkedList<Integer> lostlist = new LinkedList<>();
LinkedList<Integer> reservelist = new LinkedList<>();
for(Integer i:lost) {
	lostlist.add(i);
}
for(Integer i:reserve) {
	if(!lostlist.contains(Integer.valueOf(i))) reservelist.add(i);
}

잃어버린 사람들 번호를 lostlist에 넣음.

여벌옷 사람들 번호를 reverselist에 넣음. 혹시 lostlist에 이미 있다면 무시.

 

int answer = n;
while(true) { 
	LinkedList<Integer> nolist = new LinkedList<>(); 
	LinkedList<Integer> onelist = new LinkedList<>(); 
	LinkedList<Integer> twolist = new LinkedList<>(); 
	for(Integer i:lostlist) { 
		if(reservelist.contains(i-1)&&reservelist.contains(i+1)) twolist.add(i); 
		else if(reservelist.contains(i-1)&&!reservelist.contains(i+1)) onelist.add(i); 
		else if(!reservelist.contains(i-1)&&reservelist.contains(i+1)) onelist.add(i); 
		else if(!reservelist.contains(i-1)&&!reservelist.contains(i+1)) nolist.add(i);

lostlist 사람 중 앞뒤로 여벌옷 빌릴 수 있으면 twolist,

앞이나 뒤 하나만 빌릴 수 있으면 onelist,

그 누구에게도 빌릴 수 없으면 nolist.

	}
	for(Integer i:nolist) {
		lostlist.remove(Integer.valueOf(i));
		answer--;

빌릴 수 없으면 어차피 수업참여는 절대 불가능.

총 학생 수 n명으로 설정했던 answer에서 수 만큼 빼줌.

lostlist에서도 빼버려서 아예 고려대상에서 제외.

	}
	if(!onelist.isEmpty()) {
		for(Integer i:onelist) {
			if(reservelist.contains(i-1)) {
				reservelist.remove(Integer.valueOf(i-1));
				lostlist.remove(Integer.valueOf(i));
			}
			else if(reservelist.contains(i+1)) {
				reservelist.remove(Integer.valueOf(i+1));
				lostlist.remove(Integer.valueOf(i));
			}

두 명에게 빌릴 여유 없이 한 명에게서만 빌릴 수 있는 애들부터 구제될 생각.

빌렸으니 자신을 lostlist에서 지워주고, 빌려준 애도 이제 reverselist에서 지워줌.

		}
	} else {

처음 while문이 돌고 다시 돌아갔을 때, 빌릴 수 없는 애는 아예 사라졌고,

두 명에게서 빌릴 수 있던 애들 중 누군가는 위에서 먼저 거래가 끝나서

onelist나 nolist로 새롭게 배정될 수 있음.

nolist면 제외, onelist면 빌림받고 빌려줄 애도 고려제외..

while문을 돌다보면 onelist에 해당할 애들이 없어지고, 여유롭게 2명에게 빌릴 수 있는 애들만 고려해도 됨.

twolist가 있다면 lostlist에서 구제받으면서 제거되고, 없으면 없는대로 넘어감.

		for(Integer i:twolist) {
			lostlist.remove(Integer.valueOf(i));
		}
		answer-=lostlist.size();

아직도 lostlist에 있는 애들은 결국 여기까지 와서도 못빌리는 애들. 이 수만큼 빼준다.
(이렇게 안전장치를 걸어둔 것이지만, 아마 위 절차에서 비워졌을 것 같아 필요없을 것임..)

		break;
	}
}
return answer;

'Problem Solving > programmers' 카테고리의 다른 글

[Lv2] 스킬트리  (0) 2019.04.11
[Lv2] 주식가격  (0) 2019.04.10
[Lv1] 최대공약수와 최소공배수  (0) 2019.04.10
[Lv1] 2016년  (0) 2019.04.10
[Lv1] 소수의 합, 소수 찾기  (0) 2019.04.10
Comments

잘못된 정보가 있다면, 꼭 댓글로 알려주세요(비로그인 익명도 가능).

여러분의 피드백이 저와 방문자 모두를 올바른 정보로 인도할 수 있습니다.

감사합니다. -현록

후원해주실 분은 여기로→