일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- bargraph
- stratified k-fold
- 청산원함
- mask2cocojson
- 피처 스케일링
- spleeter
- MaskRCNN환경구축
- bcss
- rogistic regression
- flask모델서빙
- seaborn.barplot
- MaskRCNN코랩
- MaskRCNN_colab
- 회귀 평가 지표
- MSLE
- MaskRCNN환경구성
- 엘라스틱넷
- 프로그래머스
- stacking
- mask2coco
- docker
- 다중 회귀
- Python
- PyQt5
- mmdetection
- 로지스틱 회귀
- RMSLE
- 기사단원의무기
- 객체 성능 평가 지표
- 모델 성능 최적화
- Today
- Total
노트와 노트
[프로그래머스] 연습문제 - 기사단원의 무기 본문
1. 문제
https://school.programmers.co.kr/learn/courses/30/lessons/136798
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
2. 풀이
1. 1부터 주어진 수까지 반복문을 돌며 각 수의 약수 개수 count를 구한다.
2. 해당 수의 약수 개수 count 가 limit보다 클 경우(초과), 개수를 power로 변경한다.
3. count를 divisor_list에 넣고 총 합을 리턴한다.
3. 초기 작성 코드 (실패)
def solution(number, limit, power):
answer = [1]
for i in range(2, number+1):
count = 2 # 1, 자기 자신
if i > 3:
for j in range(2, int(i/2)+1):
if i % j == 0:
count += 1
if count>limit:
count = power
answer.append(count)
return sum(answer)
수많은 시간 초과의 향연...... 또르르...

4. 개선된 코드 (성공)
이전 코드에서 시간 초과 판정이 난 것을 감안해서, 연산 횟수를 줄이기 위해 2가지 Point를 개선했습니다.
개선점1
As-is
기존에는 해당 수의 약수를 구하기 위해서 주어진 수의 반절 지점까지(1/2) 확인하고 약수 판별을 진행했는데요.
To-be
사실 약수를 구할 때에는 주어진 수의 제곱근까지만 확인하면 된다는 점을 이용해서 연산 수를 줄였습니다.
자연수 n의 약수가 x라면, n/x = y 역시 n의 약수인데요. 이와 같이 자연수 n은 약수 간의 곱으로 이루어져 있으므로, 하나의 약수를 알게 되면 다른 약수 또한 구할 수 있게 됩니다.
수학적 증명은 아래 블로그 참고!
https://doodle-ns.tistory.com/32
[노트] 모든 약수를 구하는 알고리즘은 O(sqrt(n))이다.
학원 학생들이 약수를 모두 찾는 (또는 약수의 합, 개수를 구하거나, 소수 판별 등등) 코드를 어떻게 짜는지 살펴보면, 백이면 백 \(O(n)\) 알고리즘을 사용한다. 하지만 어떤 수의 모든 약수를 구
doodle-ns.tistory.com
이 점을 이용해서 약수의 개수를 구하는 코드를 짜게 되면 문제점이 하나 생기는데, 바로 9, 16, 25와 같이 같은 수의 제곱으로 이루어진 수들의 경우 중복 카운트가 된다는 것인데 해당 부분도 처리해주는 코드를 작성했습니다.
같은 수의 제곱으로 이루어지지 않은 경우에만(10 line) 추가로 count를 +1 해줌으로써 2*8과 같이 다른 수로 이루어진 경우 작은 약수와 큰 약수를 한 번에 카운트하고, 4*4와 같이 같은 수의 제곱으로 이루어진 경우에는 한 개의 수만 카운트하게 됩니다.
개선점2
As-is
기존에는 약수를 카운트하는 반복문 로직이 종료된 후, 약수의 개수가 limit보다 클 경우 power로 바꿔주는 코드였는데요.
To-be
불필요한 연산 횟수를 좀 더 줄이기 위해서 반복문 내에 count가 limit보다 클 경우 바로 count를 power로 바꾸고 약수를 구하는 반복문을 종료하도록 하는 코드를 추가했습니다.
def solution(number, limit, power):
answer = [1]
for i in range(2, number+1):
count = 2 # 1, 자기 자신
for j in range(2, int(i**0.5)+1): # 개선점 1 적용
if i % j == 0:
count += 1
if j*j != i: # 개선점 1 적용 (중복 처리)
count+=1
if count>limit: # 개선점 2 적용
count = power
break
answer.append(count)
return sum(answer)
완료!
'Algorithm & DataStructure' 카테고리의 다른 글
[프로그래머스] 연습 문제 - 소수 찾기 (0) | 2023.12.31 |
---|---|
[자료구조] 우선순위 큐(Priority Queue) (0) | 2023.10.30 |
[알고리즘] 이진 탐색(Binary Search) (0) | 2023.09.20 |
[알고리즘] DFS(Depth-First Search)/BFS(Breath First Search) (0) | 2023.09.20 |