노트/알고리즘

정렬, 이진 탐색, 다이나믹 프로그래밍

작성

『이것이 코딩 테스트다』 6장부터 8장이다. 정렬은 sort(key=lambda x: x[1]) 로 다중 리스트를 정렬하는 연습이 전부고, 이진 탐색은 재귀와 반복문 두 가지로 구현한 뒤 부품 찾기와 떡볶이 떡 만들기에 적용했다. 부품 찾기는 set 으로 푸는 쪽이 더 간단해서 시행착오 파일을 따로 남겼다. 다이나믹 프로그래밍은 피보나치를 단순 재귀, 메모이제이션, 반복문 세 가지로 쓰고 실행 시간을 비교한 것까지만 있다.

위에서 아래로

n=int(input())
li=[]
for i in range(n):
    li.append(int(input()))
li.sort(reverse=True)
for i in li:
    print(i,end=' ')

성적이 낮은 순서로 학생 출력하기

n=int(input())
li=[]
for i in range(n):
    li.append(list(input().split())) #split으로 받으면 또 split대로 list가 나뉘는군
    li[i][1] = int(li[i][1])

li.sort(key=lambda x:x[1]) # array=sorted(key=lambda x:x[1]) 다중 리스트에서 각 요소 별로 정렬할 때 많이 쓰임

for i in li:
    print(i[0],end=' ')

두 배열의 원소 교체

n,k = map(int,input().split())
li_a=list(map(int,input().split()))
li_b=list(map(int,input().split()))

li_a.sort()
li_b.sort(reverse=True)

for i in range(k):
    if li_a[i] < li_b[i]:
        li_a[i],li_b[i]=li_b[i],li_a[i]
    else:
        break # 정렬했기 때문에 b가 더이상 크지 않으면 의미 없어 반복문 탈출

print(sum(li_a))

이진 탐색: 재귀 함수로 구현

def binary_search(array,target,start,end):
    if start > end:
        return None
    mid = (start+end) // 2

    if array[mid] == target:
        return mid
    elif array[mid] > target:
        return binary_search(array,target,start,mid-1)
    else:
        return binary_search(array,target,mid+1,end)

n,target = map(int,input().split())
array = list(map(int,input().split()))

result = binary_search(array,target,0,n-1)
if result ==None:
    print("원소가 존재하지 않습니다.")
else:
    print(f'{result+1}번째 위치에 있습니다.')

이진 탐색: 반복문으로 구현

def binary_search(array,target,start,end):
    while start <=end:
        mid = (start+end)//2
        if array[mid] == target:
            return mid
        elif array[mid] > target:
            end = mid -1
        else:
            start = mid +1
    return None

n,target = map(int,input().split())
array = list(map(int,input().split()))

result = binary_search(array,target,0,n-1)
if result == None:
    print("없음")
else:
    print(f'{result+1}위치에 있음')

부품 찾기

이진 탐색

n=int(input())
array=list(map(int,input().split()))
m=int(input())
targets=list(map(int,input().split()))

def binary_search(array,target,start,end):
    while start <= end:
        mid = (start+end)//2
        if array[mid] == target:
            return 'yes'
        elif array[mid] > target:
            end = mid -1
        else:
            start = mid + 1
    return 'no'

array.sort()

for target in targets:
    result = binary_search(array,target,0,n-1)
    print(result, end=' ')

set 으로 (시행착오)

n=int(input())
array=list(map(int,input().split()))
m=int(input())
targets=list(map(int,input().split()))

array = set(map(int,input().split())) # -> 단순히 특정 수 체크 용도라면

for target in targets: # O(M)
    if target in array: # O(N)
        print("yes" ,end=' ')
    else:
        print("no", end=' ')

# 시간복잡도 O(M * N), 종류가 n가지가 아니라면 set방법도 괜찮음

떡볶이 떡 만들기

#1차 풀이
n,m=map(int,input().split())
li=list(map(int,input().split()))

li.sort()

# 가운데 떡길이 만큼 잘라봐서 가늠을 하는거지

def binary_search(li,m,start,end):
    h=0
    while start<=end:
        mid = (start+end)//2
        # 떡을 H만큼 잘랐을 때 나머지 길이
        sum_li = []
        for item in li:
            diff = item - li[mid]
            if diff > 0:
                sum_li.append(diff)

        # M만큼의 떡을 얻었다면 = 높이 최대
        if m == sum(sum_li):
            h = li[mid]
            break
        # m이상 이미 충분히 얻음 = 높이를 더 높여도 됌  = start 오른쪽으로 이동
        elif m < sum(sum_li):
            start = mid +1
            h = max(li[mid],h)
        # m만큼 얻지 못함. 높이를 줄여야함
        else:
            end = mid -1
    return h

print(binary_search(li,m,0,n-1))

피보나치 수열

단순 재귀

import time

def fibo(x):
    if x ==1 or x ==2:
        return 1
    return fibo(x-1) + fibo(x-2)

start = time.time()
print(fibo(6))
end = time.time()
print(round(end-start,3))

메모이제이션 (탑다운)

# memo방법 fibo (1)

import time

d = [0] * 100

def fibo_memo(x):
    if x ==1 or x == 2:
        return 1
    if d[x] !=0:
        return d[x]
    d[x] = fibo_memo(x-1)+fibo_memo(x-2)
    return d[x]

start = time.time()
print(fibo_memo(6))
end = time.time()
print(round(end-start,3))


def fibo_memo(x):
  if x==1 or x==2:
    return 1
  elif d[x] !=0:
    return d[x]
  else:
    d[x] = fibo_memo(x-1) + fibo_memo(x-2)
    return d[x]

fibo_memo(6)

반복문 (보텀업)

# memo방법 fibo (2)

import time
start = time.time()

dd = [0] * 100
dd[1] = 1
dd[2] = 1
n=30
for i in range(3, n+1):
    dd[i] = dd[i-1]+dd[i-2]
print(dd[n])

end = time.time()
print(round(end-start,3))