알고리즘 문제를 풀다보면 적절한 로직을 활용해서 Time Complexity를 만족해야하는 경우가 많다.
Time Complexity(시간복잡도)
최악의 경우 연산이 수행되는 시간을 나타내기 위해 Big-O로 나타내며, 이는 적어도 이만큼은 걸린다로 이해하면 된다.
그 외에도 Big-Omega와 Big-Theta가 있고 이들은 각각 아무리 많아도 이만큼 걸린다, 정확히 이만큼 걸린다로 해석할 수 있다.
1초는 대략 1억번의 연산이 수행될 수 있다.
시간 복잡도를 결정짓는 가장 큰 요인인 입력 크기(Input Size)와 연산(Operation)을 가지고서 계산하며, 이를 기준으로 현재 설계한 알고리즘으로 문제가 해결 될 수 있는지를 판단하면 된다.
메모리 제한은 공간 복잡도를 나타낸다.
시간 제한과 함께 메모리 제한도 주어지는데 이는 자료구조를 활용하여 데이터를 저장하는 공간의 크기로 계산하면 된다.
Java : Byte < Short,Char < Int,Long < Float,Double
배열은 동형 타입의 연속된 메모리 공간이다.
배열은 물리적으로 연속된 공간을 할당 받아서, 같은 타입을 저장하는 자료구조이다.
배열은 가변적이지 못하다는 단점으로 인해 동적 배열인 ArrayList를 활용한다.
연결리스트는 논리적으로 연속성을 부여받은 자료구조이다.
앞서 배열과 ArrayList 모두 연속된 메모리 공간을 사용하기 때문에, 새로운 데이터를 추가하거나 삭제할 때 모든 데이터가 영향을 받는다고 정리했다.
이러한 단점을 개선하기 위해 데이터와 링크로 구성된 노드를 활용해서 논리적인 연결관계를 표현한 LinkedList가 탄생했다.
방향성의 갯수와 Head,Tail의 관계에 따라 Singly,Doubly,Circular LinkedList가 존재한다.
다만, 데이터의 삽입,삭제할 타겟 노드를 찾는 과정이 O(N)인데, 이를 기억해두고 있는 Iterator를 활용하면 최초에만 O(N)이고 그 이후에는 O(1)에 해결할 수 있다.
Stack - LIFO
스택은 후입선출의 특징을 갖는 자료구조이며, 데이터의 삽입 삭제는 한 공간에서만 발생한다.
Queue - FIFO
큐는 선입선출의 특징을 갖는 자료구조이며, 데이터의 삽입 삭제는 상황에 따라 서로 다른 공간에서 발생할 수 있다.
Deque is Doubly Ended Queue
기존의 큐는 삽입과 삭제가 각각 한방향에서만 가능했다면 Deque은 그것이 양방향에서 가능하도록 구현하였다.
따라서 덱을 활용하면 Stack,Queue 처럼 사용할 수 있다.
Tree는 1:N의 관계를 갖는 비선형 자료구조
자식 노드의 수가 최대 2개인 조건이 붙으면 이진 트리(Binary Tree)
위에서 소개한 트리에서 자식 노드의 수를 최대 2개로 제한하면 우리는 이진 트리라 한다.
이진 트리는 배열로도 구현이 가능한데, 1번 인덱스부터 사용하게 되면 다음과 같은 특징을 갖는다.
트리의 순회 방법 (Pre-Order,In-Order,Post-Order)
루트 노드를 탐색하는 시점에 따라 전위,중위,후위순회로 나뉜다.
재귀 함수로 구현한다
다른 두 순회를 안다면 트리의 모습을 추측할 수 있다
이진트리 + 부모의 값이 항상 왼쪽 자식보다 크고, 오른쪽 자식보다 작다 = 이진 탐색 트리(BST)
Heap is 완전 이진 트리
객체가 생성되는 메모리 공간을 뜻하는 Heap이 아니라 최댓값 최솟값을 빠르게 찾는 자료구조 Heap은 완전 이진트리로 구현되어 있다.
힙의 생성은 n/2 노드부터 루트 노드까지 heapify를 수행한다.(logN * N)
힙의 삽입은 완전 이진 트리를 유지해야하므로 가장 마지막 위치에 삽입하고, 위치를 찾아간다.
힙의 삭제는 루트에서만 일어나며, 완전 이진 트리를 유지해야 하므로, 가장 마지값 위치의 값을 루트로 올리고, 위치를 찾아간다.
삽입과 삭제는 부모와 그리고 자식과의 비교를 통해 이루어진다 O(logN)