문제
자연수 n이 주어질때 만약 값이 123 이라면, 1+2+3을 만들라
n의 범위 : 100,000,000 이하의 자연수
나의 풀이
def solution(n): result = 0 while(n!=0): result += n%10 n = int(n/10) return result
일의 자리를 하나씩 더하는 로직을 만들었다.
n%10 : 일의 자리 추출
int(n/10) : 일의 자리 제거
다소 쉬운 문제인데 더 좋은 풀이를 보고 감탄하여 글로 적어본다.
def solution(n):
return sum(map(int,str(n)))
map 으로 쪼개고, sum으로 합치고.. 이런 생각을 어떻게 한걸까
우선, 테스트 케이스 두개를 통과 못한 코드로 틀렸는데 방법은 다음과 같다.
오답 코드
def solution(n):
for i in range(n,2,-1):
if(n%i==1):
min=i
print(i)
return min
반복자 i의 값을 max값에서 -1식 차감하며, 최소값을 탐색하는 코드를 작성했는데,
테스트 케이스 두개를 통과하지 못해 오류가 났다,
어떤 오류가 있을까 반례를 생각하던중에
"어..? 그냥, 최소값에서부터 탐색하면 되지 않나? "
그래서 수정한 코드는
def solution(n):
for i in range(2,n):
if n%i==1: return i
위의 코드로 통과했다.
max값에서 탐색하는것보다 반복 횟수도 줄이고, 훨씬 효율적인 코드로 발전했다.
접근방법
풀어낼 방법은 알고 있었지만, 이걸 어떻게하면 효율적인 코드로 짜서
반복횟수를 줄이고, 코드를 간략화 할 수 있을까? 잠시 생각을 갖게 되었다.
파이썬은 라이브러리만 잘 활요해도 복잡한 로직도, 쉽게 해결할 수 있어서 고민을 해보고
이것 저것 시도해보다 결국 반복문을 사용하기로 했다.
def solution(n):
arr = []
while n!=0 :
arr.append(n%10)
n = int(n/10)
arr.sort(reverse=True)
result = 0
i = 1
for j in range(len(arr)):
result += arr.pop()*i
i *= 10
return result
나의 풀이 방법
우선 정수의 요소들을 일의자리부터 하나하나 리스트에 담아둔후,
리스트에 담아두고 내림차순으로 정렬시키고서
pop을 이용해 i부터 일의자리 ,십의자리 차례대로 result에 담아 반환했다.
반복문을 두개나 사용해서 비효율적이라 생각했는데, 명쾌한 답이 잘 생각이 나질 않았다.
더 좋은 풀이 코드
def solution(n):
result = list(str(n))
result.sort(reverse=True)
return int("".join(result))
코드가 훨씬더 직관적이고 간결해지게 되었다.
result를 반환받은 값의 문자열 리스트로 생성하고,
내림차순 정렬하고
결합한 문자열을 int형으로 형변환 하여 반환한다.
같은 답을 도출할지라도, 얼마나 효율적이며 직관적인지는 코딩의 중요한 요소인 것 같다.
python으로 구현하기 다소 어렵지 않은 내용인데,
다른사람의 코드 리뷰를 보고서 큰 충격을 받았다.
나의 풀이
def solution(s):
return int(s) if s.count("-")==0 else int(s.replace("-",""))*-1
삼항 연산자를 이용해 문자열 '-'이 있나 체크하고,
없다면 형변환 하여 출력하고
있다면 제거하여 형변환 한 값을 음수로 만들어 반환했는데.
더 좋은 풀이
def solution(s)
return int(s)
...? 이게 왜 가능하지? 싶은 코드였다.
아무래도 문자 '-' 자체를 프로그램 내에서 친절하게 분석까지 해주는 모양이다.
하샤드 수
문제를 풀때마다 이런 하샤드 수, ... 법칙 등등 접할때마다 두려워 했는데
문제를 읽고나서 그다지 어렵지 않다는걸 깨달았다,
그럼에도 글을 작성한 이유는 또 배운것이 있기 때문이다.
나의 풀이
def solution(s):
return True if s%sum(map(int,str(s))) == 0 else False
코드를 간략화하여 한줄에 끝내봤다.
map으로 쪼개서, sum 값을 구해내고,
조건에 맞다면 리턴 하도록 코드르 구성했는데.
더 간략화한 코드
def solution(s):
return s%sum(map(int,str(s))) == 0
잘 보면 출력은 True,False중 한가지만을 찾고있다.
따라서 삼항연산을 할 필요없이 연산한 값이 0이 맞는지만 작성한다면
True,False를 반환하게 된다.
피보나치, 팩토리얼 관련해서 재귀함수를 사용하는 방법을 공부한적이 있었는데,
n의 값이 100,000이 최대값이란걸 확인하고서 더빨리 구할 수 있는 방법을 찾아
강의를 듣고 공부하고나서 풀이했다.
def solution(n):
dp = [0]*100001
dp[1] = 1
for i in range(2,n+1):
dp[i] = dp[i-1] + dp[i-2]
return int(dp[n]%1234567)
링크 >> 피보나치 재귀,dp,리스트 를 이용한 나의 공부
피보나치 관련 알고리즘을 확실하게 이해할 수 있게 돕는 좋은 문제인 것 같다.
접근 방법
입력 s 의 문자들을 자세히 보면 모든 문자가 공백으로 띄어져있다.
그렇다는건?
1. 문자열을 공백을 기준으로 쪼개고
2. 쪼개진 요소들을 리스트에 담고
3. max와 min 함수를 이용하면 된다.
def solution(s):
result = [int(i) for i in s.split(' ')]
return f"{min(result)} {max(result)}"
문제를 풀며 깨달은 것
자세히보면 반복자 i를 int형으로 형변환 한것을 알 수 있다.
이는, 문자열 타임과, 정수형 타입에서
max 함수와 min 함수가 동작은 하지만, 음수값을 거꾸로 계산하기에
int형으로 형변환이 필요했다.