드디어…

20240322123248

네이버 공채가 열렸다는 소식이 들렸다. 작년에도 1차 서류 통과는 했었고 드디어 때가 온 게 아닌가 싶다.

사실 대단한 일은 아니라고 생각한다. 아마 성실하게 하신 분들이라면 어렵지 않게 통과할 것이다. 작년 같은 경우에도 지금보다도 포트폴리오는 준비가 확실하지 않았으나 1차를 합격했었던 것으로 미루어 볼 때 진짜는 코딩 테스트를 통과 이후가 아닐까 싶다.

적성 검사까지 잘 맞을 수 있을지, 걱정 보단 조금이라도 손을 놀려서 파이썬 문제 풀이 방식을 익혀야지 ㅠ

코테.. 자신이 없긴 하지만 그래도 작년과는 다르다..! 마지막 스퍼트로 python 핵심 코테 기술들 위주로 정리하면서 학습 하려고 한다. 토요일 오전에 치는 시험… 목표는 3문제 중 2문제라도 맞추기다. 😂😂


알게된 핵심 내용 위주

  • 사전 자료형에서 데이터를 찾아 탐색하는 것은 생각보다 시간 복잡도가 크지 않아 탐색 시 속도가 빠르다. 단 키가 주어질 때 이야기다
  • 정규식을 활용하기 위해 re 라이브러리를 import 해서 쓰는 것은 편하지만(간지도 난다ㅋㅋ), 프로그래머스든, 백준이든 막상 돌려보면 굉장히 시간 복잡도 면에서 불리하다. 어차피 입력에 대해서 보통 파싱이 필요하면 split()을 활용하면 된다. 하물며 프로그래머스 방식은 배열 구조로 값을 제공하므로 정규화가 필요한 경우는 드무니 가능하면 머릿속에서 배제하고 방법을 간구하자.
  • 정수의 부호를 제외한 정확한 절대값을 얻고 싶을 땐 abs()
  • iterate 한 대상 두개의 값을 함께 묶어서 한번에 for문에서 돌리는 방법은 zip()을 활용하면 된다.
  • list 컴프리헨션 중에 유의미하게 도움 될만한 것은 다음 패턴이다. x x for x in iterableObject if condition
  • 리스트 컴프리헨션에서 맨 앞에오는 대상은 연산으로 값을 수정하면서 넣기도 가능하다.
def solution(a, b):
    return sum(A*B for A, B in zip(a, b))
  • 위에서 보다 확장되어서 리스트 컴프리헨션을 활용시, if, else 구문을 넣어서 값을 컨트롤하면 이렇게도 가능하다.
    return sum(A if numbersDict[A] % 2 == 0 else -A for A in numbersDict) 
  • 이진수로 변환하는 개꿀팁! bin() 대신 출력에서 0b가가 함께 나오니 주의할 것
  • iterable 객체에 대해서는 .reverse() 라는 방식으로 자기 스스로를 뒤집는 방식과 reversed()라는 형식으로 객체를 집어 넣는 방법이 있다.
  • n ** 3 = 3제곱! 제곱 연산을 구현하기 빡세니 기억해둘것
  • enumerate() 메소드는 iterable 객체를 넣었을 때, 리스트 컴프리헨션 기능을 통해 해당 값의 인덱스를 같이 호출해준다.
  • min, max와 같은 메서드는 인자들을 넣어도 되며, 리스트를 넣으면 최소 값을 받아낸다.
  • iterableObject.remove()는 특정 객체를 삭제하는데 사용할 수 있다. 그러나 str 객체는 수정 불가하므로 지우는 것이 불가능하다.
  • dictionary 구조는 매우 유용하다. 잘 기억해둘것. 특히 컴프리핸션에서 쓸 수 있는 keys(), values() 는 각각 키와 값을 리스트로 저장하는 것이 가능하다.
  • ~ed 메소드들은 iterable 객체를 넣을 시 자연스럽게 list 형 객체를 리턴한다.
  • dictionary 객체를 만들 때 길이를 알고 키는 자동 생성을 한다면 다음 형태를 쓰면 유효하다.
    player = {x:[] for x in range(n)}
  • LRU 캐시 구조
from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity):
        self.cache = OrderedDict()
        self.capacity = capacity
        
    def get(self, key):
        if key not in self.cache:
            return -1
        else:
            self.cache.move_to_end(key)
            return self.cache[key]
        
    def put(self, key, value):
        if key in self.cache:
            self.cache.move_to_end(key)
        self.cache[key] = value
        if len(self.cache) > self.capacity:
            self.cache.popitem(last=False)
  • 특정 조합의 경우를 전부 고려해야 한다면 조합을 활용해야 하는데, 이때 필요한 것이 itertools의 combinations 이다
from itertools import combinations
import math

def isPrime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
    # 제곱근 활용해서 구하기
        if n % i == 0:
            return False
    return True

def solution(nums):
    answer = 0
    combs = list(combinations(nums, 3))
    # 조합 목록 구하기
    for val in list(sum(x) for x in combs):
        if isPrime(val):
            answer += 1
    return answer
  • min, max 등의 메서드에서 key 는 다음 예시처럼 지정하면 된다.
    for i in range(N):
        key = max(failRateList, key=failRateList.get)
        del failRateList[key]
        # print(key, " : ", i)
        answer[i] = key
    
  • 정수, 특수문자, 알파벳 등이 복합으로 되어 있는 경우 isdigit, isalpha 등의 메소드를 활용하면 편리하게 구분이 가능하다.
  • 위 아래 좌 우로 움직이는 경우는 dx, dy를 활용하면 좋고, 이왕 구현하는거 1, 0 , -1 이 아니라 받아내는 좌표를 활용해서 해놓으면 불필요한 연산을 줄일 수 있다.
def solution(board, h, w):
    dx = [w, w+1, w, w-1]
    dy = [h-1, h, h+1, h]
    answer = 0
    for i in range(4):
        if dy[i] < 0 or dy[i] >= len(board):
            continue
        if dx[i] < 0 or dx[i] >= len(board[0]):
            continue
        if board[h][w] == board[dy[i]][dx[i]]:
            answer += 1
    return answer
  • 문자열 중 특정 내용을 전체에서 빼고 싶다면 .sub() 메소드를 활용하자. 주의 사항은 re 라이브러리의 import 는 필수라는 것
answer = re.sub("[^a-zA-Z0-9_.-]", "", answer)
  • replace() 메소드는 특정 글자나 부분에 대해 대체해줄 수 있다.
answer = answer.replace("..", ".")
  • 리스트, 문자열 컴프리헨션의 일환으로 -1은 맨 마지막 글자를 의미한다.
answer = answer + answer[-1]
  • 정확한 날짜 계산이 필요한 케이스들은 날짜 계산 보단, 차라리 일수로 계산을 변환하여 하는 것이 정확하게 진행이 가능하다.
  • in 이라는 것 역시 일종의 메소드로 활용이 되어, 리스트 안에 무엇이 존재 여부를 확인하는 기능을 담고 있다.
if id in thisIterableList:
	break
  • popLeft 를 활용해서 들어온 출구에서 값을 빼면서 지우는거, 잘 활용하면 코드 2줄 정도 줄인다.
  • 람다 함수를 사용하는 것과, 함수 자체를 사용하여 key 등의 조건으로 넣는 것이 가능하다.
array = [('홍길동', 50), ('이순신', 32), ('아무개', 74)]

def my_key(x):
	return x[1]

print(sorted(array, key=my_key))
print(sorted(array, key=lambda x: x[1]))

# 실행결과
# [('이순신', 32), ('홍길동', 50), ('아무개', 74)]
# [('이순신', 32), ('홍길동', 50), ('아무개', 74)]
# 람다 표현식의 예시 : 여러 개의 리스트에 적용
list1 = [1, 2, 3, 4, 5]
list2 = [6, 7, 8, 9, 10]

result = map(lambda a, b: a + b, list1, list2)

print(list(result))

# 실행 결과
# [7, 9, 11, 13, 15]
  • eval = 문자열 형변환 없이 알아서 수식을 계산해주는 고마운 친구…!
  • sorted 메서드를 통해 정렬시 key는 람다로 하면 편리하다.
array = [('홍길동', 35), ('이순신', 75), ('아무개', 50)]
result = sorted(array, key=lambda x: x[1], reverse=True)
print(result)
  • 순열과 조합..!!! 이거라도 기억해두자
    • 순열 서로 다른 n 개에서 r개를 선택해 일렬로 나열하는 것
    • 조합 : 서로 다른 n 개에서 순서 상관없이 서로 다른 r개를 선택하는 것
from itertools import permutations
# 순열에서 이용 가능한 라이브러리

data = ['A', 'B', 'C'] # 데이터 준비
result = list(permutations(data, 3))# 모든 순열 구하기
print(result)

# 실행결과
# [('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
from itertools import combinations
# 기억해!!!itertools!!!!

data = ['A','B','C'] # 데이터 준비

result = list(combinations(data, 2))
print(result)

# 실행 결과
# [('A', 'B'), ('A', 'C'), ('B', 'C')]
  • Counter 기능
    • iuterable 한 객체를 넣고, 값으로 찾으면 내부 원소에서 몇 번째에 있는지를 알려준다. dict 짱 유용함
from collections import Counter

counter = Counter(['red', 'blue', 'red', 'gree', 'blue', 'blue'])
print(counter['blue'])
print(counter['green'])
print(dict(counter))

# 실행 결과
# 3
# 1
# ('red': 2, 'blue': 3, 'green',: 1)
  • 최대 공약수와 최소 공배수, 항상 구현하기 빡센데 한번에 끝내자…!
    • math 라이브러리를 참고하자
import math

def lcm(a,b)
	return a * b // math.gcd(a, b)

a = 21
b = 14

print(math.gcd(21, 14)) # 최대 공약수(GCD) 계산
print(lcm(21, 14)) # 최소 공약수(LCM) 계산

# 실행 결과
# 7
# 42
  • 유클리드 호제법 최대 공약수 계산 방식
def gcd(a, b):
	get = a % b
	if get == 0 :
		return b
	return gcd(b, get)

print(gcd(192, 162))
  • DFS 는 재귀 + 방문 여부를 통해 확실하게 방문 안한 곳에 대해서 방문하는 구조면 된다. 대신 방향성이 없어야 가능하니 주의
    • BFS와 차이점, 우선 가능한 기준 루트 노드에서 1차 뎁스를 다보고 다음으로 가냐, 반대로 1차 뎁스에서, 2, 3차까지 깊게 들어갔다 나오냐.

일단 프로그래머스 가장 난이도 높은 카카오 LV1~2 몇 문제까진 풀수 있었다. 파이썬이고, 그래도 강의를 좀 보면서 문법에 빨리 적응이 되서 다행이다. 새벽에 일어나서 추가적으로 방법론좀 더 머리속에 넣고 딱 2문제만 제대로 풀었으면…!