반응형

문제 13: 회문 찾기

큐와 스택 

: '줄 서기'에 비유할 수 있습니다. FIFO

스택: '접시 쌓기'에 비유할 수 있습니다. LIFO

def palindrome(s):

  qu = []

  st = []

  for x in s:

    if x.isalpha():

      qu.append(x.lower())

      st.append(x.lower())

  while qu:

    if qu.pop(0) != st.pop():

      return False

  return True

isalpha() : 주어진 문자가 알파벳 문자에 해당하는지 확인하는 기능

 

 

문제 14 . 동명이인 찾기 딕셔너리

 

def find_same_name(a):

   name_dict = {}

   for name in a:

     if name in name_dict:

        mame_dict[name] += 1

     else:

        mame_dict[name] = 1

   result = set()

   for name in name_dict:

      if name_dict[name] >= 2:

        result.add(name)

   return result

 

문제 15. 친구의 친구 찾기 그래프

 

def print_all_friends(g, start):

  qu = [] 

  done = set()

  qu.append(start)

  done.add(start)

  while qu:

    p = qu.pop(0)

    print(p)

    for x in g[p]:

      if x not in done:

        qu.append(x)

        done.add(x)

 

###친밀도 계산

def print_all_friends(g, start):

  qu = [] 

  done = set()

  qu.append((start,0))

  done.add(start)

 

  while qu:

    (p ,d) = qu.pop(0)

    print(p,d)

    for x in g[p]:

      if x not in done:

        qu.append((x,d+1))

        done.add(x)

 

05. 응용문제

문제 16. 미로 찾기 알고리즘

모델링이란 주어진 현실의 문제를 정형화하거나 단순화하여 수학이나 컴퓨터 프로그램으로 쉽세 설명할 수 있도록 다시 표현한다는 것을 말합니다.

일단 미로 정보를 입력한다.

 

미로 찾기 알고리즘

그래프 탐색 과정에서 지금까지 지나온 경로를 문자열로 만들어 큐에 추가한 것과 탐색 중 목적지 에 도착하면 탐색을 멈추도록 한 것을 제외하면 그래프 탐색 알고리즘과 완전히 같은 알고리즘입니다.

def solve_maze(g, start, end):
	qu = []
    done = set()
    
    qu.append(start)
    done.add(start)
    
    while qu:
    	p = qu.pop(0)
        v = p[-1]
        if v == end:
        	return p
        for x in g[v]:
        	if x not in done:
            	qu.append(p+x)
                done.add(x)
    
    return "?"

 

17. 가짜 동전 찾기 알고리즘

겉보기에는 똑같은 동전이 n개 있습니다. 이 중에서 한 개는 싸고 가벼운 재료로 만들어진 가짜 동전입니다. 좌우 무게를 비교할 수 있는 양팔 저울을 이용해서 다른 동전보다 가벼운 가짜 동전을 찾아내는 알고리즘을 만들어 보세요.

방법 1: 하나씩 비교하기

이 방법은 원하는 값을 찾기 위해 자료를 차례로 하나씩 비교하는 순차 탐색과 비슷합니다.

def weigh(a,b,c,d):
	fake = 29
    if a <= fake and fake <= b:
    	return -1
    if c<= fake and fake <=d:
    	return 1
    return 0
   
def find_fakecoin(left, right):
	for i in range(left+1, right+1):
    	result = weight(left, left, i,i)
        if result == -1:
        	return left
        elif result == 1:
        	return i
    return -1

 

방법 2: 반씩 그룹으로 나누어 비교하기

def weigh(a,b,c,d):
	fake = 29
    if a <= fake and fake <= b:
    	return -1
    if c<= fake and fake <=d:
    	return 1
    return 0
   
def find_fakecoin(left, right):
	if left == right:
    	return left
       
    half = (right-left+1) //2
    g1_left = left
    g1_right = left+ half-1
    g2_left = left+half
    g2_right = g2_left+half -1
    result = weight(g1_left, g1_right,g2_left, g2_right)
    if result == -1:
    	return find_fakecoin(g1_left,g1_right)
    elif result == 1:
    	return find_fakecoin(g2_left,g2_right)
    else:
    	return right

문제 18 최대 수익 알고리즘

어떤 수식에 대해 특정 기간 동안의 가격 변화가 주어졌을 때 , 그 주식 한 주를 한 번 사고 팔아 얻을 수 있는 최대 수익을 계산하는 알고리즘을 만들어 보세요.

방법 1:  가능한 모든 경우를 비교하기

def max_profit(prices):
	n = len(prices)
    max_profit = 0
    
    for i in range(0, n-1):
    	for j in range(i+1, n):
        	profit = prices[j]- prices[i]
            if profit > max_profit:
            	max_profit = profit
    return max_profit

방법 2: 한 번 반복으로 최대 수익 찾기

def max_profit(prices):
	n = len(prices)
    max_profit = 0
    min_price = prices[0]
    
    for i in range(1, n):
    	profit = prices[i] - min_price
        if profit > max_profit:
        	max_profit = profit
        if prices[i] < min_price:
        	min_price = price[i]
    return max_profit

 

 

 

 

출처 : 모두의 알고리즘 with 파이썬 

반응형
반응형

탐색은 : 여러 개의 자료 중에서 원하는 것을 찾아내는 것

정렬은 : 주어진 자료를 순서에 맞춰 나열하는 것

 

07. 순차 탐색 

 

주어진 리스트에 특정한 값이 있는지 찾아 그 위치를 돌려주는 알고리즘

sequential search

 

1. 순차 탐색으로 특정 값의 위치 찾기

def search_list(a, x):

  n = len(a)

  for i in range(0,n):

     if x == a[i]:

        return i

  return -1

 

2. 알고리즘 분석

계산 복잡도 O(n)

 

08. 선택 정렬

1. 선택 정렬로 줄 세우기

2. 쉽게 설명한 선택 알고리즘

def find_min_idx(a):

   n = len(a)

   min_idx = 0

   for i in range(1, n):

      if a[i] < a[min_idx]:

         min_idx = i

   return min_idx

 

def sel_sort(a):

  result = []

  while a:

     min_idx = find_min_idx(a)

     value = a.pop(min_idx)

     result.append(value)

  return result

 

3. 일반적인 선택 알고리즘

def sel_sort(a):

  n = len(a)

  for i in range(0,n-1):

    min_idx = i

    for  j in range(0,n-1):

      if a[j] < a[min_idx]:

         min_idx = j

  a[i], a[min_idx] = a[min_idx], a[i]

 

4. 알고리즘 분석

O(n^2)

 

09. 삽입 정렬 

리스트 안의 자료를 작은 수 부터 큰 순서로 배열하는 정렬 알고리즘

1. 삽입 정렬로 줄 세우기

2. 쉽게 설명한 삽입 정렬 알고리즘

def find_ins_idx(r, v):

  for i in range(0, len(r)):

     if v < r[i] :

       return i

  return len(r)

def ins_sort(a):

  result = []

  while a:

    value = a.pop(a)

    ins_idx = find_ins_idx(result , value)

    result.insert(ins_idx , value)

  return result

3. 일반 적인 삽입 정렬

def ins_sort(a):

  n = len(a)

  for i in range(1, n):

    key = a[i]

    j = i-1

    while j >= 0 and a[j] < key:

       a[j+1] = a[j]

       j -= 1

    a[j+1] = key

4. 알고리즘 분석 

O(n^2)

 

문제 10 : 병합 정렬

리스트 안의 자료를 작은 수부터 큰 수 순서로 배열하는 정렬 알고리즘을 만들어 보세요.

1. 병합 정렬로 줄 세우기

2. 쉽게 설명한 병합 정렬 알고리즘

def merge_sort(a):

  n = len(a)

  if n <= 1:

    return a

  mid = n //2

  g1 = merge_sort(a[:mid])

  g2 = merge_sort(a[mid:])

  result = []

  while g1 and g2:

    if g1[0] < g2[0]:

      result.append(g1.pop(0))

    else:

      result.append(g2.pop(0))   

    while g1:

      result.append(g1.pop(0))

    while g2:

      result.append(g2.pop(0))

  return result

3. 병합 정렬에서의 재귀 호출

4. 일반적인 병합 정렬 알고리즘 

def merge_sort(a):

  n = len(a)

  if n <= 1:

    return

  mid = n //2

  g1 = a[:mid] 

  g2 = a[mid:]

  merge_sort(g1)

  merge_sort(g2 )

  i1 = 0

  i2 = 0

  ia = 0

  while i1< len(g1) and i2< len(g2):

    if g1[i1] < g2[i2]:

      a[ia] = g1[i1]

      i1 += 1

      ia += 1

    else:

      a[ia] = g2[i2]

      i2 += 1

      ia += 1

  while i1< len(g1):

      a[ia] = g1[i1]

      i1 += 1

      ia += 1

  while i2< len(g2):

      a[ia] = g1[i2]

      i2 += 1

      ia += 1

  5. 알고리즘 분석

 

문제 11. 퀵정렬

그룹을 둘로 나눠 재귀 호출하는 방식

def quick_sort(a):

  n = len(a)

  if n <=1:

    return a

  pivot = a[-1]

  g1 = []

  g2 = []

  for i in range(0,n-1):

    if a[i] < pivot:

      g1.append(a[i])

    else:

      g2.append(a[i])

  return quick_sort(g1)+[pivot] + quick_sort(g2)

 

def quick_sort_sub(a, start, end):

  if end - start <= 0:

     return 

  pivot = a[end]

  i = start

  for j in range(start, end):

    if a[j] <= pivot:

      a[i], a[j] = a[j] , a[i]

      i+=1

  a[i],a[end] = a[end],a[i]

  quick_sort_sub(a, start, i-1)

  quick_sort_sub(a, i+1, end)

 

def quick_sort(a):

  quick_sort_sub(a, 0, len(a)-1)

 

문제 12. 이분 탐색

둘로 나눈다 탐색할 자료를 둘로 나누어 찾는 값이 있을 법한 곳만 탐색하기 때문에 자료를 하나하나 찾아야 하는 순간 탐색보다 원하는 자료를 훨씬 빨리 찾을 수 있습니다.

 

def binary_search(a, x):

  start = 0

  end = len(a) -1

  while start <= end:

    mid = (start+end)//2

    if x == a[mid]:

      return mid

    elif x > a[mid]:

      start = mid +1

    else:

      end = mid-1

  return -1

 

 

 

 

 

 

출처 : 모두의 알고리즘 with 파이썬 

반응형
반응형

알고리즘: 간단히 말해 '어떤 문제를 풀기 위한 절차나 방법'입니다.

입력 ->과정 -> 출력

 

문제: 어떤 숫자의 절댓값 구하기

입력 : 절댓값을 구할 실수 a

출력 : a의 절댓값

 

알고리즘 분석: 알고리즘의 성능이나 특징을 분석하는 것 

 

 

첫째마당 알고리즘 기초

문제 01: 1부터 n까지의 합 구하기

입력 : 1....2

출력 : 5050

입력 -> 알고리즘 -> 출력

def sum_n(n):

  s = 0

  for i range(1,n+1):

    s = s + i

  return s

 

알고리즘 분석: 

 

def sum_n(n):

  return n * (n+1) //2

 

계산복잡도 complexity:어떤 알고리즘이 문제를 풀기 위해 해야 하는 계산이 얼마나 복잡한지 나타낸 정도

 

02. 최댓값 찾기

def find_max(a):

  n = len(a)

  max_v = a[0]

  for i in range(1,n):

    if a[i] > max_v:

      max_v = a[i]

  return max_v

 

 

03. 동명이인 찾기

def find_same_name(a):

  n = len(a)

  result = set()

  for i in range(0,n-1):

    for j in range(i+1, n):

      if a[i] == a[j]

        result.add(a[i])

  return result

 

 

02. 재귀호출

재귀호출은 함수가 자기 자신을 다시 호출하는 것을 뜻합니다.

04. 팩토리얼 구하기

1부터 n까지의 곱 , 즉 팩토리얼 구하는 문제 

 

  • 1.팩터리얼 

def fact(n):

  f = 1

  for i in range(1, n+1):

    f = f*i

  return f

 

  • 2. 러시아 인형

 

  • 3. 재귀호출 : 다시 돌아가 부르기

RecursionError:특정 조건이 되면 더는 자신을 호출하지 않고 멈추도록 설계하지 않으면 

계속 반복하다가 재귀 에러가 난다. 

 

  • 4. 재귀호출 알고리즘

def fact(n):

   if n <= 1:

     return 1

   return n * fact(n-1)

 

  • 5. 알고리즘 분석

계산 복잡도 O(n)

 

종료 조건이 없으면 재귀 에러 나 스택 오버플로 등 프로그램 에러가 발생해 비정상적인 

동작을 할 수 도 있다. 

 

05. 최대 공약수 구하기 

두 자연수 a와 b의 최대 공약수를 구하는 알고리즘

 

  • 1. 최대 공약수 알고리즘

최대 공약수 성질

1. 두 수 중 더 작은 값을 i에 저장한다.

2. i가 두 수의 공통된 약수인지 확인한다.

3. 공통된 약수이면 이 값을 결괏값으로 돌려주고 종료한다.

4. 공통된 약수가 아니면 i를 1만큼 감소시키고 2번으로 돌아가 반복합니다.(1은 모든 

정수의 약수이므로 i가 1이되면 1을 결괏값으로 돌려주고 종료합니다.

 

def gcd(a,b):

  i = min(a,b)

  while True:

     if a % i == 0 and b % i ==0:

        return i

     i = i - 1

 

  • 2. 유클리드 알고리즘 

def gcd(a,b):

  if b == 0:

    return a

  return gcd(b, a % b)

 

06. 하노이의 탑 옮기기 

 

  • 1. 하노이의 탑 

간단한 원반 옮기기 퍼즐 이다.

크기가 다른 원반 n개를 출발점 기둥에서 도착점 기둥으로 전부 옮겨야 한다.

원반은 한 번에 한 개씩만 옮길 수 있다

원반을 옮길 때는 한 기둥의 맨 위 원반을 뽑아 , 다른 기둥의 맨 위로만 옮길 수 있다.

원반을 옮기는 과정에서 큰 원반을 작은 원반 위로 올릴 수 없다.

 

  • 2. 하노이의 탑 
  • 3. 하노이의 탑 알고리즘 

1-A: 원반이 한개면 그냥 옮기면 끝 (종료 조건)

1-B: 원반이 n개일 때

   1 : 1번 기둥에 있는 n개 원반 중 n-1개를 2번 기둥으로 옮깁니다.

   2 : 1번 기둥에 남아 있는 가장 큰 원반을 3번 기둥으로 옮깁니다.

   3 : 2번 기둥에 있는 n-1개 원반을 다시 3번 기둥으로 옮깁니다.

 

def hanoi(n , from_pos, to_pos, aux_pos)

   if n == 1:

     print(from_pos , "->", to_pos)

     return

 

   honoi(n-1, from_pos, aux_pos, to_pos)

   print(from_pos,"->", to_pos)

  honoi(n-1, aux_pos, to_pos, from_pos)

 

  • 4. 알고리즘 분석 

O(1): n과 무관하게 일정한 시간이 걸림

O(n): n과 비례하여 계산 시간이 증가함

O(n^2): n의 제곱에 비례하여 계산 시간이 증가함

O(2^n): 2의 제곱에 비례하여 계산 시간이 증가함

 

출처: 모두의 알고리즘 with python

반응형

' > 모두의 알고리즘 with 파이썬' 카테고리의 다른 글

04. 자료구조,05. 응용문제  (0) 2020.08.30
셋째 마당 : 탐색과 정렬  (0) 2020.08.27

+ Recent posts