Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[01주차 김동주] 소트 #1

Merged
merged 1 commit into from
Oct 21, 2023
Merged

[01주차 김동주] 소트 #1

merged 1 commit into from
Oct 21, 2023

Conversation

hepheir
Copy link
Member

@hepheir hepheir commented Oct 9, 2023

  • 제목: 소트
  • 분류:
    • 그리디

🖊️ 풀이

  • 시간 복잡도: $O(N^2)$
  • 입력의 크기:
    • $N \leq 1,000$

스택과 카운터에 기반한 탐욕 알고리즘으로 풀이하였습니다.

  1. 사용가능한 모든 숫자와 각 숫자의 개수를 파악한다.
  2. 스택에 숫자를 하나 씩 쌓아가면서 수열을 생성한다. 사용된 숫자는 카운터에서 사용된 횟수만큼 차감한다.
  3. 수열에 새로 삽입 할 숫자는 $A_i+1 \neq A_{i+1}$을 만족하면서, 아직 카운터에 남아있는 숫자 중에서 사전 순으로 선정한다.

플레티넘 문제 치고는 상당히 쉬운 난이도였던 것 같습니다. 여러분도 도전해보세요!

Comment on lines +4 to +8
def solve(N: int, A: list[int]):
counter = [0] * (MAX_NUM+1)
for a in A:
counter[a] += 1
build(N, counter)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문제에서 숫자의 배열이 주어지는데 숫자는 최대 50개고, 각 숫자는 1,000보다 작거나 같은 자연수 또는 0입니다.

이것을 연속된 두 수가 연속된 값이 아니게만 정렬하면 되는데,
우선 각 숫자의 등장 횟수를 세어봅시다.

Comment on lines +11 to +20
def build(N: int, counter: list[int], stack: list[int] = []):
if len(stack) == N:
print(' '.join(map(str, stack)))
exit()
for n in generate_possible_numbers(counter, stack):
stack.append(n)
counter[n] -= 1
build(N, counter, stack)
counter[n] += 1
stack.pop()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이어서 각 숫자 별 등장 횟수를 센 counter 배열과, 스택만으로 문제에서 요구하는 수열을 만들 수가 있습니다.

스택에는 만들어진/완성된 수열이 담기게 됩니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 아직 스택 활용하는 부분이 익숙치 않은데 이런식으로 적용하면 비슷한 다른 문제도 다양하게 적용시킬 수 있겠군요 참고하겠습니다 ㅎㅎ

Comment on lines +12 to +14
if len(stack) == N:
print(' '.join(map(str, stack)))
exit()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

모든 숫자를 다 채웠으면 완성된 수열을 출력하고 프로그램을 종료합니다.

Comment on lines +16 to +20
stack.append(n)
counter[n] -= 1
build(N, counter, stack)
counter[n] += 1
stack.pop()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서는 가능한 수열 조합을 그리디하게 만들어가다가, 더 이상 문제의 조건을 만족하는 수열을 만들 수 없을 때 다시 stack의 top으로 되돌아가며 다른 조합을 찾아보게 됩니다.

뒤로 돌아가서 다시 추적을 한다는 의미에서 백트레킹이라고 부를 수 있지 않을까 싶네요

stack.pop()


def generate_possible_numbers(counter: list[int], stack: list[int]):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저.. 좀 초짜같은 놀라움이긴 한데요, 파이썬에서 이렇게 타입 지정할 때 리스트 안에 들어갈 타입까지도 지정이 가능한 걸 지금 알았네요.
요즘 파이썬으로 프로그램 작성하면 최대한 타입 지정해서 사용하려고 하는데, 참고해보겠습니당.. ☺️

def generate_possible_numbers(counter: list[int], stack: list[int]):
for i in range(MAX_NUM+1):
if counter[i] > 0 and (not stack or i != stack[-1]+1):
yield i
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yield 라는 키워드를 처음봐서 검색해보고 왔는데 성능 측면에서 이점을 보기위해서 사용한다고 하는데 그점을 노리고 사용하신건지 아님 또 다른 이유가 있는지 궁금합니다

Comment on lines +11 to +20
def build(N: int, counter: list[int], stack: list[int] = []):
if len(stack) == N:
print(' '.join(map(str, stack)))
exit()
for n in generate_possible_numbers(counter, stack):
stack.append(n)
counter[n] -= 1
build(N, counter, stack)
counter[n] += 1
stack.pop()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 아직 스택 활용하는 부분이 익숙치 않은데 이런식으로 적용하면 비슷한 다른 문제도 다양하게 적용시킬 수 있겠군요 참고하겠습니다 ㅎㅎ

@hepheir hepheir merged commit ad12c17 into dsa-master:main Oct 21, 2023
1 of 12 checks passed
hepheir added a commit that referenced this pull request Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants