인프런 커뮤니티 질문&답변

zhu님의 프로필 이미지

작성한 질문수

세계 대회 진출자가 알려주는 코딩테스트 A to Z (with Python)

그리디 알고리즘 [문제풀이] : BOJ 1461

고생했던? 케이스에 대해 선생님의 코드가 어떻게 들어맞는 지에 대한 질문이 있습니다. ㅠ

해결된 질문

24.08.08 20:52 작성

·

120

·

수정됨

0

안녕하세요, 강의를 듣고 계신 여러분!

여러분의 학습을 돕기 위해 질문 안내를 드리고자 합니다.

 

1. chatGPT를 이용해보기

  • 단순한 의문은 chatGPT를 이용해도 해답을 찾을 수 있는 경우가 종종 있습니다!

     

 

2. 강의의 어떤 부분에 대한 질문이고, 어떤 부분이 궁금한지 명확히 알려주세요!

  • 강의의 어느 파트에서 의문을 느끼고, 어떤 부분이 궁금한지를 명확히 제시해 주시면 답변에 도움이 됩니다!

  • 자신은 어떻게 이해했는지 또한 적어주면 좋습니다!

 

ex) 섹션5의 '그래프 순회 (DFS & BFS) [개념]' 강의에서 DFS와 BFS 모두 그래프의 모든 노드를 탐색하는 알고리즘이라고 하셨고 시간 복잡도 또한 똑같다고 이해했습니다. 그러면 DFS와 BFS 중에서 어떤 알고리즘이 더 효율적인지 구별하는 것은 의미가 없는 것일까요?

 

  • 어느 파트

    • 섹션5의 '그래프 순회 (DFS & BFS) [개념]' 강의

  • 자신은 어떻게 이해했는지

    • DFS와 BFS 모두 그래프의 모든 노드를 탐색하는 알고리즘이라고 하셨고 시간 복잡도 또한 똑같다고 이해

  • 어떤 부분이 궁금한지

     

    • DFS와 BFS 중에서 어떤 알고리즘이 더 효율적인지 구별하는 것은 의미가 없는 것일까요?

안녕하세요!

강의 잘 듣고 있습니다.

백준 1461 그리디 마지막 문제에 대한 질문이 있는데요.

 

보기 전에 풀어보긴 했는데,

두더지 잡다가 어떻게 된 느낌이긴 해요..

음,, 아직 습관이 안 고쳐지기는 했는데 정의하고 분석하고 따져보고 그려본 다음에 해야 하는데,,

 

그 제가 처음 푼 방식은

리스트 요소를 지워가며 해결하는 방식인데요

  1. 양/음수가 m으로 떨어지지 않는 나머지 경우를 먼저 따져 합계에 더하고, 제거한 뒤

  2. 먼 데부터 다녀오는데, 최댓값을 계속 갱신해서

  3. 가장 먼 거리를 나중에 빼주는 방식으로 했어요..

m으로 나누어 떨어지지 않는 경우에 대한 처리를 나중에 추가했는데요

선생님의 코드가 어떻게 그 경우도 잘 처리하는 지 분석이 잘 안되어서..

설명 부탁 드려요..

 

아! 저번 설명 너무 감사합니다

 

  • 더불어 약간 공부하는 루틴?이랄까? 그런 것도 말씀해 주실 수 있는 게 있다면 혹시 말씀 부탁드려요..(코테 공부도 그렇고 다른 것도 그렇고..)

 

아래는 제가 처음 정답 받은 코드입니다.

(코드가 지저분함에 죄송해요..)

import sys
input = sys.stdin.readline

# 방향을 결정하고 상자 들고 다음에 처음 갈 책 위치를 반환합니다.
def getPos(arr):
	global direction
	maximum = max(map(abs, arr))
	if maximum in arr: 
		if len(arr) > m:
			direction = False
			if min(arr) >= 0: 
				direction = True
				return 0
			for i in range(len(arr) - 1, -1, -1):
				if arr[i] < 0: return i
		else:
			direction = True
			for i in range(len(arr)):
				if arr[i] >= 0: return i
	else: 
		if len(arr) > m:
			direction = True
			if max(arr) < 0:
				direction = False
				return len(arr) - 1
			for i in range(len(arr)):
				if arr[i] >= 0: return i
		else:
			direction = False
			for i in range(len(arr) - 1, -1, -1):
				if arr[i] < 0: return i
	return -1

n, m = map(int, input().rstrip().split())
arr = list(sorted(map(int, input().rstrip().split())))

cnt = 0; direction = True; reach = 0; plusCount = 0; minusCount = 0

#양수/음수 따로 헀어야 좋았는데, 하다보니 개수 세는 걸 만들었어요..
def count():
	global plusCount, minusCount
	for i in arr:
		if i >= 0: plusCount += 1
		elif i < 0 : minusCount += 1

count()

#양수 m으로 나누어 떨어지지 않을 경우에 대한 처리입니다.
if plusCount % m != 0:
	mini = min(i for i in arr if i >= 0)
	idx1 = arr.index(mini)
	idx2 = min(arr.index(mini) + (plusCount % m), len(arr))
	reach = arr[idx2 - 1]
	for i in range(idx1, idx2):
		arr.remove(arr[idx1])
	cnt += reach * 2

#음수 m으로 나누어 떨어지지 않을 경우에 대한 처리입니다.
if minusCount % m != 0:
	maxi = max(i for i in arr if i < 0)
	idx1 = arr.index(maxi)	
	idx2 = max(arr.index(maxi) - (minusCount % m), -1)
	far = abs(arr[idx2 + 1])
	for i in range(idx1, idx2, -1):
		arr.remove(arr[idx2 + 1])
	cnt += far * 2
	reach = max(reach, far)

# 이럴 필요 없는데, 돌면서 먼 데 구하고 그 안쪽? 지우는 방식으로 했어요..
while arr:
	pos = getPos(arr)
	far = abs(arr[min(len(arr) - 1, pos + m - 1) if direction else max(0, pos - m + 1)])

	for i in range(m):
		if not arr: break
		arr.remove(arr[pos])
		if not direction or pos == len(arr): pos = max(pos - 1, 0)
	cnt += far * 2
	reach = max(reach, far)

print(cnt - reach)

답변 2

1

알리 Ally님의 프로필 이미지
알리 Ally
지식공유자

2024. 08. 11. 15:40

안녕하세요. zhu님!

 

질문하신 요지를 정리해보자면,

제가 작성한 코드에서 M으로 나누어 떨어지지 않는 경우를 별도로 처리하지 않았는데,

어떻게 정답 처리가 되는지 궁금하신걸로 파악되는데요.

제 코드 내에 해당 케이스가 모두 포함되어 처리되어 있습니다.

 

아래는 백준 1461에서 제공된 테스트 케이스입니다.

이를 기반으로 설명드리겠습니다.

7 2
-37 2 -6 -39 -29 11 -28

위 테스트 케이스를 각각 양수와 음수로 나눈뒤, 거리(절대값)로 변환하며 내림차순으로 정렬하면 다음과 같습니다.

pos = [11, 2]
neg = [39, 37, 29, 28, 6]

여기서 M단위로 탐색하기 위해 pos[::M], neg[::M]으로 각각의 리스트를 나누면 다음과 같습니다.

pos[::M] = [11]
neg[::M] = [39, 29, 6]

pos[::M]에서 11은 11까지 거리를 가면서 2거리의 책까지 챙기는 작업을 포함하여 11이 담긴 것으로 이해하시면 됩니다.

마찬가지로 neg[::M]에서 39는 39와 37, 29는 29와 28, 6은 6의 거리에 있는 책을 챙기는 작업을 포함합니다.

 

즉 내림차순으로 정렬하여 0번째 인덱스 부터 M단위로 탐색한 거리를 넣게되면,

담긴 각 거리는 M개씩 책을 챙기는 케이스 중 가장 먼 거리를 담게되고, 나누어 떨어지지 않는 음수 양수의 마지막 케이스도 함께 담게 됩니다.

위와 같은 원리로 M으로 떨어지지 않는 경우에도 모든 케이스를 포함하게 됩니다.

 

공부법과 관련해서는 질문자님의 구체적인 상황을 잘 알지 못하기 때문에 말씀드리기 어렵습니다.

대신 제 개인적인 공부 루틴을 간략하게 소개해드리자면 다음과 같습니다.

  • 한 가지 공부를 할 때 기본적으로 2-3번 본다는 생각

  • 1회독: 가볍게 들으며 이해가 안 가는 부분은 따로 메모

  • 2회독: 중요한 부분은 무엇인지 생각하며, 1회독에서 이해가 안 갔던 부분을 해결해보기

  • 3회독: 관련 내용들을 직접 실습해보기

추가로 공부법과 간련하여 영상 중간중간 참고하시면 좋을 부분들을 첨부해드립니다.

  • 코딩테스트 공부의 상한선 04:48

  • 강의를 200% 활용하는 법 00:00 ~ 02:55

  • '실전 문제풀이1' 파트

  • 문제를 푸는 사고과정 ('실전 문제풀이2' 파트 소개) 01:54 이후부터 끝까지

 

또 궁금하신 점 있으시면 언제든 질문 부탁드립니다.

감사합니다. :)

1

인프런 AI 인턴님의 프로필 이미지

2024. 08. 10. 20:56

안녕하세요, 인프런 AI 인턴입니다.

님의 질문은 프로그래밍 강의와 관련된 질문이지만, 제공된 정보 내에서는 직접적으로 님이 질문하신 내용에 대한 답변을 찾을 수 없습니다. 강의의 특정 내용이나 코딩 문제에 대한 해설에 대해서는 직접 해당 강의의 지식공유자나 그와 관련된 공식 플랫폼을 통해 질문하는 것이 좋습니다.

그리고 코딩테스트 준비나 공부 방법에 대한 일반적인 조언을 원하시면, 인프런에는 다양한 알고리즘 및 프로그래밍 관련 강의가 준비되어 있고 여러 고급 개발자들과의 멘토링을 신청하여 추가적인 조언을 얻을 수 있습니다.

멘토링 신청하러 가기

멘토링 후기 살펴보기

강의 내용과 관련해 좀 더 구체적인 답변이 필요하시면, 강의 페이지 내 수강 전 문의 게시판을 활용하시거나 해당 강의의 질문과 답변 섹션을 이용해 보시길 권장드립니다. 코딩테스트 및 프로그래밍 학습에서 궁금한 점이 있을 때는, 질문을 명확하게 정리하여 문의하시면 도움을 받기가 더 용이합니다.

혹시 다른 프로그래밍 관련 도움이 필요하시면 언제든지 질문해주세요.

zhu님의 프로필 이미지

작성한 질문수

질문하기