Programming/Algorithm

억지 기법과 완전 탐색

ParkJinseok 2021. 10. 19. 14:45

선택 정렬

      • 억지 기법에서의 전략
        • 정렬이 안된 리스트에서 최솟값이 선택되면 이 값을 새로운 리스트에 저장하는 것이 아니라 첫 번째 요소와 교환한다.
        • 어떤 정렬 알고리즘이 입력 리스트 이외에 추가적인 메모리를 사용하지 않으면 "제자리(In-place) 정렬"이라고 부른다.
        • 선택 정렬의 장점
          • 알고리즘이 간단하고, 입력자료의 구성과 상관없이 자료 이동 횟수가 결정된다는 장점
          • 입력의 크기가 크지 않은 실제 문제에 충분히 사용 가능
        • 선택 정렬의 단점
          • 다른 정렬 알고리즘에 비해 효율적이지도 않고, 안정성을 만족하지도 않음
      • Python Code
        더보기
        data = [5,3,8,4,9,1,6,2,7]
        
        def printStep(arr, val):
            print(" Step %2d  = " % val, end='')
            print(arr)
        
        def selection_sort(A):
            n = len(A)
            for i in range(n-1):
                least = i
                for j in range(i+1, n):
                    if(A[j]<A[least]):
                        least = j
                A[i], A[least] = A[least], A[i]
                printStep(A, i+1);
        
        print ("Original : ", data)
        selection_sort(data)
        print("Selection : ", data)
      • 복잡도 분석
        • 선택 정렬의 시간 복잡도는 O(n^2)

    순차 탐색

      • 컴퓨터에서 탐색은 가장 많이 사용되는 작업 중 하나임
      • 탐색은 주어진 항목들 중에서 "탐색키"라 불리는 원하는 값을 가진 항목을 찾는 것
      • 억지 기법에서의 전략
        • 입력 리스트의 첫 항목부터 순서대로 하나씩 탐색키와 비교하는 순차 탐색(Sequential Search) 또는 선형 탐색(Linear Search)
        • 순차 탐색의 장점
          • 리스트가 정렬되어 있지 않다면 이 방법 외에 별다른 대안이 없음
          • 가장 직접적인인 탐색 알고리즘으로 간단하고 구현하기 쉬움
        • 순차 탐색의 단점
          • 효율적이지 않음
      • Python code
        더보기
        def sequential_search(A,key):
        for i in range(len(A)):
            if A[i] == key:
                return i
        return -1
      • 복잡도 분석
        • 최선의 경우
          • 리스트의 첫 번째 항목이 Key인 경우, 한번의 비교만으로 탐색이 종료됨.
          • O(1)
        • 최악의 경우
          • 찾고자 하는 숫자가 리스트에 없거나 맨 뒤에 있는 경우로 모든 항목을 검사해야 함
          • O(n)

    문자열 매칭

      • 원하는 키워드나 문자열을 찾고 싶은 경우
      • 억지 기법에서의 전략
        • 텍스트의 첫 번째 문자 위치에 패턴을 놓고 비교한다. 이 과정을 패턴을 오른쪽으로 한 칸씩 옮기면서 성공한 매칭이 나타날 때까지 반복한다.
      • Python code
        더보기
        def string_matching(T,P):
        n = len(T)          
        m = len(P)
        for i in range(n-m+1):
            j =0
            while j < m and P[j]==T[i+j]:
                j = j+1
            if j==m:
                return i
        return -1
      • 복잡도 분석
        • 입력의 크기는 텍스트의 길이 n과 패턴의 길이 m
        • 최선의 경우
          • 텍스트 T의 맨 앞의 문자열이 패턴 P와 일치하는 경우
          • 패턴의 길이인 m번만 비교하면 문자열 매칭이 종료 되므로, O(m)이다
        • 최악의 경우
          • 텍스트의 길이 n만큼 움직이고 패턴의 길이 m만큼 모든 문자마다 비교하게 되므로 O(nm)이다

    최근접 쌍의 거리(Closest-pair)

      • 억지 기법에서의 전략
        • 가능한 모든 점의 쌍에 대해 거리를 계산하고, 가장 짧은 것을 찾는다
        • 유클리드 거리
      • Python code
        더보기
        def closest_pair(p):
        n = len(p)
        mindist = float("inf")
        for i in range(n-1):
            for j in range(i+1,n):
                dist = distance(p[i],p[j])
                if dist < mindist:
                    mindist = dist
        return mindist
      • 복잡도 분석
        • 입력의 크기는 전체 점의 수 n
          기본 연산은 유클리드 거리 계산 문장인 (distance(p[i], p[j]))
        • 시간 복잡도는 O(n^2)

      완전 탐색(Exhaustive Search)

        • 완전 탐색은 가능한 모든 경우의 수를 탐색하는 것
        • 모든 경우의 수를 탐색하기 때문에 오래 걸리지만, 절대 답이 틀릴 일이 없다
        • 외판원 문제(Traveling Saleman Problem, TSP)
          • TSP는 가중치 그래프에서 가능한 모든 해밀토니안 사이클중에서 경로의 합이 최소인 사이클의 경로의 합을 구하는 것
          • 해밀토니안 사이클
            • 그래프 G=(V,E)가 주어졌을 때, G의 임의의 한 정점에서 출발하여 다른 모든 정점을 한번씩만 방문하고 다시 시작 정점으로 돌아오는 경로
              해밀토니안 사이클
          • 억지 기법에서의 전략
            • 임의의 한점을 출발점으로 잡고 아직 가보지 않은 모든 이웃 정점으로 계속 이동하면서 검사
          • 복잡도 분석
            • 완전 탐색 기법은 순열(또는 조합, 부분 집합) 객체들을 생성하는 과정이 필요한 경우가 많아서 복잡도가 매우 높음
              ex)TSP에서 도시의 수가 n이라면 O(n!)가 됨
              순열과 조합
        • 0-1 배낭 채우기 문제(Knapsack Problem)
          • 배낭의 용량을 초과하지 않으면서 배낭에 들어있는 물건들의 가치의 합이 최대가 되도록 물건들을 선택하는 문제
          • 억지 기법에서의 전략
            • n개의 물건의 집합에 대한 모든 부분집합을 만들어 보고, 부분집합중에서 무게 합이 배낭 용량을 넘지 않으면서 가치가 최대인 것을 찾는 방법
          • 복잡도 분석
            • 원소의 개수가 n인 집합의 부분 집합의 수는 2^n이므로, O(2^n)이다

      일 배정 문제(Job Assignment Problem)

        • 비용을 최소화하는 방법으로 모든 근로자에게 하나씩 일을 배정하는 방법을 찾는 문제
          각각의 근로자는 모든 일을 다 처리할수 있지만 일마다의 비용을 다름
        • 복잡도 분석
          • 순열 문제이므로, O(n!)

      그래프 탐색

        • 그래프 탐색, 또는 순회는 하나의 정점에서 시작하여 모든 정점을 한 번씩 방문하는 작업
        • 그래프 순회에 완전 탐색의 개념을 적용하면 모든 정점을 체계적으로 방문 할 수 잇는 두 가지 방법을 얻을 수 있음
        • 깊이 우선 탐색(Depth First Search, DFS)
          • 스택을 이용한 미로 탐색과 유사
          • 미로 탐색할 때 한 방향으로 갈 수 있을 때까지 가다가 더 이상 갈 수 없게 되면 다시 가장 가까운 갈림길로 되돌아와서 다른 방향을 다시 탐색하는 전략
          • Python code
            더보기
            def dfs(graph, start, visited):
                if start not in visited:
                    (visited.add(start))
                    print(start, end=' ')
                    nbr = graph[start] - visited
                    for v in nbr:
                        dfs(graph, v, visited)
          • 복잡도 분석
            • 깊이 우선 탐색은 그래프의 모든 가선을 조사하므로 정점의 수가 n이고 간선의 수가 e인 그래프인 경우 인접리스트로 표현한다면 O(n+e)이다
            • 정점의 수에 비해 간선의 수가 매우 적은 희소 그래프의 경우엔 인접행렬이 유리할 것으로 예상 할 수 있음
              인접행렬과 인접리스트
        • 너비 우선 탐색(Breadth First Search, BFS)
          • 시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회 방법
          • 가까운 거리에 있는 정점들을 차례로 저장하고 들어간 순서대로 꺼낼 수 있는 큐(Queue)구조가 적합함
          • Python code
            더보기
            import queue
            
            def bfs(graph, start):
                visited = {start}
                que = queue.Queue()
                que.put(start)
                while not que.empty():
                    v = que.get()
                    print(v, end=' ')
                    nbr = graph[v] - visited
                    for u in nbr:
                        visited.add(u)
                        que.put(u)
          • 복잡도 분석
            • 너비 우선 탐색은 거리가 0인 시작 정점으로부터 거리가 1인 모든 정점, 2인 모든 정점 등의 순서대로 모든 정점을 방문하는 것
            • 인접 리스트로 표현할 경우 O(n+e)이고, 인접 행렬로 표현할 경우 O(n^2)

      'Programming > Algorithm' 카테고리의 다른 글

      분할 정복 기법  (0) 2021.10.21
      축소 정복 기법  (0) 2021.10.21
      점근적 성능 분석 방법  (0) 2021.10.12
      알고리즘 효율성  (0) 2021.10.10
      기본적인 자료구조  (0) 2021.10.07