프로그래머스 level 1,2 정리

kiki·2024년 11월 14일
0

기본기

목록 보기
9/9

range

  • 증가폭이 0이면 안된다.
    • range에서 3번째 인자인 증가폭(step)이 0일 경우 오류 남! 유의해서 코드 작성하기

string

  • reversed
    • 문자열을 뒤집어주는 함수.
    • 참고: 리스트는 [::-1]과 같이 쓸 수 있음
  • zfill
    • str.zfill(n)과 같이 사용하며, str이 n 길이 만큼 0으로 채워줌(왼쪽)
    • ex) '234'.zfill(5) -> '00234' 반환
  • rjust, ljust
    • str.rjust(n,'0')과 같이 사용하며, rjust는 왼쪽, ljust는 오른쪽에 특정 문자를 str의 길이가 n이 되도록 채워줌
  • replace
    • str.replace('.','',1) 이런식으로 세번째 인자로 해당 문자를 replace할 횟수를 지정할 수 있다.
  • capitalize, title
    • str.capitalize()과 같이 사용하며, 맨 첫번째 문자를 대문자로 변환해 반환
    • str.title()과 같이 사용하며, 숫자/특수문자/공백으로 구분된 각 단어의 첫 문자를 대문자로 변환해 반환.
  • split
    • str.split(' ')과 같이 공백으로 문자열을 split 했을 때, 공백이 두 번 연속되는 경우 ''가 두 공백 사이 문자로써 split된다.

리스트 특정 원소 제거

  • del
    • del arr[1]과 같이 사용함
  • pop
    • arr.pop(1)과 같이 사용
    • del과 같이 인덱스를 사용해 값을 반환 받고 제거한다.
    • 만약 인덱스를 지정하지 않고 arr.pop()과 같이 쓴다면, 마지막 원소를 반환 후 제거
    • pop(0)은 O(n)임을 인지하고 있을 것!
  • remove
    • arr.remove(x)와 같이 제거할 값을 인자로 사용.
    • x가 여러개 있을 경우, 가장 앞의 x를 삭제
    • 반환값이 없는 함수!

약수

  • 약수 개수가 홀수? 짝수?
    • 제곱수만 약수 개수가 홀수임
  • 약수 빠르게 구하기
    • 바로 for i in range(1, num**(0.5)+1)의 범위에서 나머지 연산이 0인지 확인하고, 그 값이 제곱수만 아니라면 i와 num//i를 약수로 추가하면 됨

문자열

  • 정렬
    • 리스트처럼 sort, sorted 모두 사용 가능
    • 대문자가 소문자보다 아스키코드 값이 작기 때문에 작은 것으로 sort됨
  • .isdigit()
    • 해당 문자열이 숫자로만 이루어져있는지 확인할 수 있는 함수

min함수 사용법

  • 이 문제에서 min을 특이하게 return 조건문에 사용할 수 있다.

itertools

  • combinations
    • combinations(list, n)과 같이 사용해, list에서 n개의 원소를 갖는 조합을 뽑을 수 있다.
  • permutations
    • permutations(list, n)과 같이 사용해, list에서 n개의 원소를 갖는 순열을 뽑을 수 있다.
  • product
    • 두 개 이상의 리스트/집합 끼리의 데카르트 곱을 구할 수 있다. 두 개 이상의 리스트의 조합을 구할 수 있음
    • product(*a)와 같이 사용해, 이중 리스트인 a에서 조합들을 구할 수 있음
    • 이 문제 참고
    • product('AEIOU', repeat=i)와 같이 repeat 인자를 사용해 같은 리스트/문자열/집합의 조합들을 구할 수도 있음

math

  • comb (조합)
    • comb(a,b)와 같이 사용해 aCb를 구할 수 있다.

collections

  • deque
    • 데크라고 하며, queue이지만 앞 뒤로 pop, append가 가능한 자료형이다.
    • popleft, appendleft 등의 함수로 앞에서 데이터를 뽑고, 넣을 수 있다. (리스트를 queue로 사용하며 pop(0)을 하면 빅오가 O(n)이지만 popleft()는 빅오가 O(1)이다.
    • 리스트와 유사하며, 메소드도 대부분 동일하다.

sort

  • 정렬 조건 여러개 지정하기
    • key=lambda x: x[0]과 같이 정렬 조건을 지정해줄 수 있는데, 여러 개의 조건을 사용하고싶을 경우, key=lambda x: (x[0],x)와 같이 정렬 조건을 괄호로 묶어 전달하면 된다.
  • 조건 여러개 오름/내림 차순 다르게 설정
    • key=lambda x: (-x[0],x)와 같이 -를 사용하면 해당 조건에 대해선 내림차순으로 정렬할 수 있다.

bin

  • 10진수 -> 2진수 변환시 사용하는 함수이다.
  • 이진수 &, | 연산
    • bin(de1|de2)와 같이 사용하면, 십진수인 de1과 de2를 이진수로 변환 후 or 연산을 한 이진수 값을 반환받을 수 있다.

dictionary

  • dict(zip(arr1, arr2))해서 두 리스트를 하나의 딕셔너리로 만들 수 있다.
  • dictionary.get(name, 0)과 같이 get을 써서 value를 가져올 때, key가 없는 경우 오류가 나는 것을 막을 수 있다.

for-else 문

for문에서 break로 빠져나오지 않고 끝까지 실행되었다면 else문이 실행된다!

for i in range(2,num+1):
	if num%i==0:
    	break
else:
    cnt+=1

이런식으로 나의 경우엔 소수인지 아닌지 판별할 때 사용했다!

while에서도 동일하게 while-else문을 사용할 수 있다.

Counter

  • 뺄셈, 덧셈 지원
    • Counter 객체(?)끼리 뺄셈, 덧셈이 가능하다! 두 카운트의 차이를 확인할 수 있음
  • 교집합, 합집합 지원
    • 교집합 시 최솟값을 취하고, 합집합 시 최대값을 취한다.
  • Counter(~).most_common()
    • value 기준으로 내림차순 정렬된 items 값을 반환한다. 그냥 Counter(~).items()를 for문으로 돌면 정렬되지 않은 값을 반환하기 때문에 주의!
  • ==
    • 당연히 같은지 아닌지도 비교 가능
  • dict to Counter dict
    • 그냥 Counter(dictionary)와 같이 감싸주면 끝!

집합, set

  • add
    • list의 append와 같이 원소를 추가하는 함수
  • in
    • set의 in은 리스트보다 훨씬 빠르다. set이 해시테이블을 기반으로 구현되어있기 때문에 빅오가 O(1)임

부등호

  • if 8<n<10과 같이 양쪽에 부등호를 동시에 사용할 수 있다..! 왜 까먹고있었지

리스트가 비어있는지 확인

  • len(my_list)==0
  • not my_list -> 리스트가 비어있으면 True를 반환

최대공약수, 최소공배수

  • 최대 공약수 (Greatest Common Divisor, gcd)
    • math 라이브러리의 gcd 함수 사용
    • 두 수 a,b (a>b)가 주어졌을 때, a%b를 r이라고 할 때, a와 b의 최대 공약수는 b와 r의 최대 공약수와 같다.
    • 요렇게 말하면 복잡한데, 결론은 큰수를 작은 수로 나눠, 나머지가 0이 될 때의 작은 수가 최대공약수라는 것임. 파이썬으로 코드를 작성하면 아래와 같다.
  def gcd(a,b):
    while b!=0:
      a,b = b, a%b
    return a
  • 최소 공배수 (Least Common Multiple)
    • 최소공배수는 최대 공약수를 이용해 구할 수 있다!
    • 두 수 a,b가 주어졌을 때, a*b/gcd(a,b)가 a와 b의 최소 공배수이다.

zip(*arr)

  • zip은 여러 iterable을 병렬로 묶어 각 요소를 튜플로 반환한다.
  • *는 리스트나 튜플을 언패킹한다! 이중 리스트를 단일 리스트 각각으로 반환하는 것
  • 즉, *로 이중 리스트를 각각의 리스트로 반환하고, 각 리스트에서 요소를 병렬로 반환하는 것이므로 이차원 리스트를 전치해서 for문을 돌고싶을 때 사용할 수 있다.
  • for column in zip(*arr)와 같이 사용 가능

all, any

  • all(iterable): iterable 자료형에서 모든 값이 True라면 True를 반환
  • any(iterable): iterable 자료형 중 하나라도 True 값을 가지면 True를 반환
    예문: any([i>max_value for i in list]) -> list를 돌며 하나의 값이라도 max_value보다 크다면 True를 반환

10진수 -> n진수

## 변환하고싶은 수
num = 18
## 변환하고싶은 진수
n = 16 

result = ''
while num>0:
  num, div = num//n, num%n
  result+=str(div)
print(result[::-1])

n진수로 변환하고싶을 때, 위와 같이 몫과 나머지를 이용해서 진수 변환이 가능하다.
이 문제에서 사용했다.

진수 변환이 주 task가 아닌 경우, 2진수 <-> 10진수는 아래와 같이 함수를 사용할 수 있음

  • 이진수 to 십진수: int(binary_value, 2) (이때 binary_value는 str)
  • 십진수 to 이진수: bin(decimal) (이때 decimal은 int)
    • bin의 반환 타입은 str이며 0b1010와 같은식. 그렇기 때문에 우리가 직접 이진수를 다루기 위해선 bin(decimal)[2:]와같이 사용

heapq

  • heap
    • 최대값, 최소값 연산을 빠르게 할 수 있는 자료구조. 완전이진트리
    • 최대 힙(부모노드 >= 자식노드), 최소 힙(부모노드 <= 자식노드)
from heapq import heapify, heappush, heappop

num = [1,2,5,2,5,6,8]

## list to heap
heapify(num)
heappush(num, 4)

## 최소값 pop
heappop(num)
## 최소값 단순 확인
print(num[0])

노드의 삽입과 삭제의 빅오가 O(logN)이다! 여기서 logN은 힙(완전이진트리)의 높이에 해당
최대값, 최소값 연산 및 데이터 삽입 및 삭제 시 유용하게 사용될 것 같다.

re (정규표현식)

  • re.split(pattern, string): 패턴에 따라 문자열을 분리하여 리스트로 반환
  • re.findall(pattern, string): 패턴에 매칭되는 모든 부분을 찾아 리스트로 반환

예제)
파일명 정렬

sorted(files, key=lambda file : (re.split('\d+', file.lower())[0],int(re.findall('\d+', file)[0])))
  • /d는 숫자(0-9)를 의미
  • +는 하나 이상의 숫자에 매칭
  • 즉 첫번째는 정규표현식은 연속된 숫자 문자열을 기준으로 file.lower()을 분리해 리스트로 반환
  • 두번째 정규표현식은 연속된 숫자 문자열을 찾아 리스트로 반환
  • 만약 숫자가 아닌 문자를 기준으로 분리하거나, 찾고싶다면 /d+ 대신 /D+를 사용하면 된다.

warning!

making odd character -> 공백을 다루는 방법
시저암호 -> 아스키코드 활용
모의고사 -> 같은 리스트를 뺑글뺑글 돌아야할 때, 인덱스에 % 연산을 사용하자
실패율 -> 나누기 연산할 때, 분모가 0이 되지 않도록! (런타임 에러)
햄버거 만들기 -> 슬라이싱과 pop 사용에서 성능 차이가 크게 남. 주의할 것

  • arr = arr[:-4](O(4))와 for _ in range(4): arr.pop()(O(1))의 차이

달리기 경주 -> 리스트와 dictionary 둘을 모두 이용해 문제를 풀어야함 (딕셔너리가 index 용도로 사용됨)
n^2 배열 자르기 - 아이디어로 풀어야하는 문제
의상 - 조합을 사용하면 너무나 쉽게 풀 수 있는 문제 (경우의 수를 생각)
전화번호 목록 - 문자열의 특성을 이해하면 쉽게 풀 수 있는 문제 (sort!)

알고리즘

0개의 댓글