"코딩 인터뷰 완전분석"이라는 책에 나온 내용이다.
순서로 진행하는게 좋다고 하는데 강사님은 무식하게 푸는 것에 공감을 많이 한다고 했다.
링크
1. 리스트 컴프리헨션으로 뼈대 구성
def solution(data):
홀수 = [i % 2 != 0 for i in data]
짝수 = [i % 2 == 0 for i in data]
print(홀수, 짝수)
return data
solution([1, 2, 3, 4, 5])
1-1. 조건에 맞게 수정
def solution(data):
홀수 = [i % 2 != 0 for i in data]
짝수 = [i % 2 == 0 for i in data]
# print(홀수, 짝수)
return [sum(짝수), sum(홀수)]
2-1. 나머지를 활용한 풀이
def solution(num_list):
answer = [0, 0]
for i in num_list:
answer[i % 2] += 1
return answer
# 좋은 풀이는 아님
# sum은 순회를 돈다!
def solution(data):
짝수 = [i % 2 == 0 for i in data]
return [sum(짝수), len(data) - sum(짝수)] # sum이 순회합니다.
# 예시
def solution(array, height):
pass
solution([149, 180, 192, 170], 167)
데이터의 형태가 리스트인데 여러개의 리스트로 구현되있는 등의 경우에는 언패킹을 해서 사용하는 편이 가독성이 좋다!
def solution(data):
array, height = data
pass
solution([[149, 180, 192, 170], 167])
def solution(array, height):
count = 0
for i in array:
if i > height:
count += 1
return count
# filter는 len가 없다
def solution(array, height):
return list(filter(lambda x: x> height, array))
위의 코드에서 filter는 len() 함수를 쓸 수 없는데 이는 순회(loop) 돌기 전까지 실행이 되지 않는 함수라서 그렇다. 수강생중 한분이 했던 말이 더 와닿을 수도 있을 것 같다.
"주문만 하고 아직 제조되지 않은 커피"
def solution(array, height):
return sum(map(lambda x: x > height, array))
solution([149, 180, 192, 170], 167)
def solution(array, height):
return sum(i > height for i in array)
solution([149, 180, 192, 170], 167)
# 오답, 그러나 이렇게도 많이 사용한다.
def solution(my_string):
count = 0
for i in my_string:
if i.isdigit():
count += 1
solution("aAb1B2cC34oOp")
def solution(my_string):
result = 0
for i in my_string:
if i.isdigit():
result += int(i)
return result
solution("aAb1B2cC34oOp")
# isdigit에 () 가 있고 없고의 차이는 무엇인가?
def 함수(x):
return x.isdigit()
def solution(my_string):
return list(filter(함수, my_string))
solution("aAb1B2cC34oOp")
괄호가 있으면 함수이고, 아니라면 메서드
2. 효율적이진 않은 코드
# 문법 복습차원
def solution(my_string):
return sum(map(int,(filter(str.isdigit, my_string))))
solution("aAb1B2cC34oOp")
2-1. 효율적이진 않은 코드
def solution(my_string):
return sum(map(lambda x: int(x) if x.isdigit() else False, my_string))
solution("aAb1B2cC34oOp")
이 문제는 정규표현식으로도 풀 수 있는데, 이때 들어가는 r이 무엇일까? re.sub(r'무언가', '', 데이터)에서 r이다.
여기서 r은 raw(날것)이라는 뜻으로 이스케이프 문자를 포함해서 전부에서 원하는 문자만 뻡겠다는 것이다.
참고로 정규표현식에서 \로 시작하는 문자는 이스케이프 문자이다. \n, \t 등
3. 정규표현식
import re
def solution(s):
return sum(map(int, re.findall(r'[0-9]', s)))
solution('aAb1B2cC34oOp')
3-1. 정규표현식
import re
def solution(s):
return sum(map(int, (re.sub(r'[a-zA-Z]', '', s))))
solution('aAb1B2cC34oOp')
def solution(cipher, code):
return cipher[code-1::code]
solution("dfjardstddetckdaccccdegk", 4)
def solution(cipher, code):
count = 1
for i in cipher:
if count == code:
print(i)
count = 0
count += 1
solution("dfjardstddetckdaccccdegk", 4)
def solution(cipher, code):
count = 1
for i, j in enumerate(cipher, 1):
if i % code == 0:
print(j)
solution("dfjardstddetckdaccccdegk", 4)
1.문자열 count
def solution(order):
order = str(order)
return order.count('3') + order.count('6') + order.count('9')
import re
def solution(order):
order = str(order)
return len(list(re.findall(r'[369]', order)))
set("people") # 중복 제거 완료, 그러나 순서를 보장하지 않음!
def solution(s):
answer = ''
for i in s:
if i not in answer:
answer += i
return answer
def solution(my_string):
return ''.join(dict.fromkeys(my_string))
solution('people')
3번은 중요하니 짚고 넘어가겠다. dict.fromkeys()로 문자열의 각 원소를 키로 딕셔너리를 만들었다. 그 다음 join으로 합치는데 딕셔너리에서 join을 하면 key값 끼리 합쳐진다!
import collections
# collections.Counter("olleh") == collections.Counter("hello")
# collections.Counter("olleh") == collections.Counter("hhhhhhhhhello")
collections.Counter("olleh")
def solution(before, after):
a = list(after)
for i in before:
if i in a:
a.remove(i)
else:
return 0
if a:
return 0
return 1
solution("olleh", "hello")
반복문에서 if문을 많이 활용하여 예외처리를 하는게 좋다. 리소스도 별로 잡아먹지 않는다고 한다.
# 'hello' => 'elloh' => 'llohe'
# 'hello' => 'ohell' => 'lohel'
# collections.deque를 사용해서 풀면 쉽게 풀림
# 문제1 'hello'를 앞뒤로 이동시켜 'llohe'를 만들 수 있나?
# 문자열을 2배한다
# 'hellohello'
# 문제2 몇칸 이동했나?
# 문자열을 2배해서 인덱스를 찾기
# 'hellohello'.index('llohe')
# 예시
# 십진수 3숫자마을
# 1 1
# 2 2
# 3 4
# 4 5
# 5 7
# 6 8
# 7 10
# 8 11
# 9 14
# 10 16
# 숫자 크기만큼 False배열을 만들고
조건에 맞는 부분만 True로 바꿔서 구현
def solution(num):
return list(filter(lambda x: (x % 3 != 0) and
('3' not in str(x)), range(1000)))[num-1]
solution = lambda n:[i for i in range(10000) if i % 3 != 0 and '3' not in str(i)][n-1]
# 예시
# emergency result
# [3, 76, 24] [3, 1, 2]
def solution(emergency):
pass
solution([3, 76, 24] )
문제는 이런식으로 접근한다.
data = ['제주', '경기', '전주'] # ['064', '031', '063']
data2 = {
'제주': '064',
'경기': '031',
'전주': '063'
}
[data2[i] for i in data]
# emergency result
# [3, 76, 24] [3, 1, 2]
def solution(emergency):
sorted_emergency = sorted(emergency, reverse=True)
return [sorted_emergency.index(i) + 1 for i in emergency]
solution([3, 76, 24])
# [3, 10, 28, 30, 12] => [17, 10, 8, 10, 8]
# [3, 10, 28, 30, 12] => [(17, 3), (10, 10), (8, 28), (10, 30), (8, 12)]
# 원하는 숫자: 20
# result: 28
array = [3, 10, 28, 30, 12]
n = 20
28 - 20 == 8
12 - 20 == -8
20 - 28 == -8
20 - 12 == 8
sorted(array, key=lambda x:(abs(x-n), x))[0]
sorted(array, key=lambda x:(abs(x-n), n-x))[0] # 팁, n-x이거나 x-n 2개 중에 하나입니다.
기본적으로 절대값으로 정렬하고, 같으면 value값이 작은 순으로 정렬한다. 순서를 바꾸고 싶으면 sorted의 두번째 조건에 n-x 혹은 x-n을 넣으면 정답이다.
# 문제 접근 방식
# i j k
# 1 13 1
i = 1
j = 13
k = 1
str(list(range(i, j+1)))
'[1, 2, 3]'.count(',')
i = 1
j = 13
k = 1
count = 0
for temp in range(i, j):
count += str(temp).count(str(k))
count
파이썬의 swap과 다른 언어의 swap은 다르다
a = 10
b = 20
# swap
temp = a
a = b
b = temp
# python에서 사용하는 swap
a = 10
b = 20
a, b = b, a
a, b
def solution(i, j, k):
return str(list(range(i, j+1))).count(str(k))
정해진 범위만큼 range로 반복하고 이를 count해주기 위해 리스트를 문자형으로 바꾸고 count를 적용하였다.
# step1
# 각 선분이 있는 곳에 총 길이 합을 구하라
# [[0, 5], [3, 5], [7, 10]]
선 = [False] * 10
선
for i in range(0, 5):
선[i] = True
for i in range(3, 5):
선[i] = True
for i in range(7, 10):
선[i] = True
sum(선)
;로 구분해서 선언 가능하다
a = 10;b = 10
a, b
# 에라토스테스트의 체 => 소수판별 => 이것을 알고리즘 문제로 내는 것은 저는 반대
소수 = [True] * 120
소수[0] = 소수[1] = False
for i in range(4, 120, 2):
print(i)
for i in range(6, 120, 3):
print(i)
# for i in range(4, 120, 4): # 2의 배수에 속하기에 할 필요가 없음
# print(i)
# https://nahwasa.com/entry/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98-%EC%B2%B4-%ED%98%B9%EC%9D%80-%EC%86%8C%EC%88%98%ED%8C%90%EC%A0%95-%EC%8B%9C-%EC%A0%9C%EA%B3%B1%EA%B7%BC-%EA%B9%8C%EC%A7%80%EB%A7%8C-%ED%99%95%EC%9D%B8%ED%95%98%EB%A9%B4-%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0
수학 공식을 활용하여 제곱근까지 반복돌리며 그 수의 배수를 False로 바꾼다. 그러면 남은 수는 자동으로 소수이다.
for 소수, 판별 in enumerate(소수):
if 판별:
print(소수)
행렬의 연산은 numpy를 활용하면 아주 쉽게 풀 수 있다!
s = [[1, 3, 5], [7, 9, 11], [13, 15, 17]]
s = np.array(s)
cols, rows = np.where(s == 7)
cols
import numpy as np
x = np.array([1, 2, 3])
x * 2
지뢰찾기와 같은 알고리즘도 쉽게 풀 수 있다!
# 지뢰찾기
x = [[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]]
x = np.array(x)
np.where(x == 1)
x = [[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]]
s = 0
for i in x:
s += i.count(1)
s
오늘은 이론보다는 실전이라는 느낌으로 코딩테스트 기본 문제들을 풀어보았다. 예전에 풀어봤던 문제들이긴 한데 몇개는 완전히 잘못 풀었다는거를 깨달았다. 좀 부끄러워 진다. 하지만! 이런 것도 마주하고 계속 정진하다 보면 어디가서 관련 지식을 뽐낼 순간이 오지 않을까? 그날을 기다리며 오늘도 공부한다
오늘이 호준 강사님의 마지막 시간이었는데 장고할때 또 오시긴 한다 ㅋㅋ. 파이썬 심화과정을 세세하게 잘 가르쳐 주시고 실무얘기를 듣는 등 어렵지만 아주 유익한 시간이었다고 생각한다. 이런 강사님들만 계신다면 끝까지 믿고 진행할 수 있을 것 같다.