CS
최장 증가 부분 수열 (LIS)
개념 어떤 임의의 수열이 주어졌을 때, 수열에서 앞에서부터 차례대로 몇 개의 숫자들을 뽑아서 부분수열을 만들 수 있다. 이렇게 만들 수 있는 부분수열 중 오름차순으로 정렬된 가장 긴 수열을 최장 증가 부분 수열(LIS, Longest Increasing Subsequence)라고 한다. 예를 들어 [5, 2, 1, 4, 3, 5] 라는 수열이 있다고 가정해보자. 해당 수열에서 최장 증가 부분 수열에 해당하는 수열은 무엇일까? 세번째에 있는 숫자 1을 꺼낸다. 다섯번째에 있는 숫자 3을 꺼낸다. 여섯번째에 있는 숫자 5를 꺼낸다. 이렇게 만들어진 수열 [1, 3, 5]가 위 수열에서 만들 수 있는 최장 증가 부분 수열에 해당하고 길이는 3이 된다. 구할 수 있는 방법에는 크게 2가지가 있고 시간 복잡도에서..
[C++] STL container 시간 복잡도 및 특징 비교
※용어 설명※ amortized : 분할 상환하다는 뜻을 가지고 있는 이 단어는, 쉽게 설명하자면 최악의 경우는 더 높은 값의 시간 복잡도를 가질 수 있지만, 대체적으로는~ 으로 생각하면 될 것 같다. 점근적 분석(Asymptotic analysis)으로 보면 O(n)이 나오는 경우에, 분할상환분석(Amortized Analysis)으로 보면 O(1)이 나오는 경우도 있기 때문이다. red-black tree: 레드블랙트리. Balanced Binary-Search Tree로 이루어진 구조. [출처] C++ STL container 시간 복잡도 및 특징 비교.|작성자 Chan
[C++] 순열 / 조합 구하기 (next_permutation/prev_permutation 함수)
순열 next_permutation C++의 algorithm 헤더에는 n개의 원소의 순열을 구할 수 있는 next_permutation이라는 함수가 있다. 기본은 오름차순이다, 즉 내림차순인 prev_permutation을 사용하기 위해서는 내림차순으로 정렬 되어있어야 한다. 중복이 있는 원소들은 제외하고 순열을 만들어준다. // default bool next_permutation (BidirectionalIterator first, BidirectionalIterator last); // custom bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, Compare comp); next_permutation ..
[알고리즘] 순열과 조합의 차이
순열과 조합의 가장 큰 차이는 순서가 있고 없고 이다. 예를 들어 자전거의 번호가 있는 자물쇠를 연다고 가정해보자. 자물쇠 번호가 1234라고 한다면 순서에 대한 고려 없이 4321을 입력하면 자물쇠는 열리지 않는다. 이를 순열이라고 한다. (순서가 있음) 또 다른 예시로 닭가슴살 샐러드를 가정해보자. 닭가슴살 샐러드의 재료는 닭가슴살, 양상추, 소스, 토마토라고 한다면 우리는 샐러드를 담을 때 닭가슴살을 처음으로 넣고 두 번째는 양상추... 이런 식으로 넣지 않고 그냥 재료에 맞게 넣는다. 이를 조합이라고 한다. (순서가 없음) 이제 수학적으로 다가가 보자 1 2 3 4 배열이 있고 2가지 경우를 뽑는다고 가정해보자 순열의 경우에는 순서가 중요하기에 하기와 같이 다 뽑아 버린다. 1 2 1 3 1 4 ..
SDK, API의 개념과 차이점
API API란 Application Programming Interface의 약자로, 모듈화하여 만들어진, 어떤 기능을 제어/제공하는 인터페이스를 말한다. 우리가 사용하는 대부분의 애플리케이션은 API에 의존하고 있다. 예) - 차량 공유 앱에서 승차 거리와 시간을 계산하는 것 👉 API의 기능 - 차량 공유 앱에서 드라이버가 픽업 위치에 도착했음을 SMS로 알 수 있는 것 👉 API의 기능 SDK SDK란 Software Development Kit의 약자로, 소프트웨어 개발 도구 모음이라고도 한다. SDK는 API, IDE, 문서, 라이브러리, 코드 샘플 및 기타 유틸리티가 포함될 수 있다. SDK는 프로그램 및 응용 프로그램 개발의 복잡성을 줄이는 강력한 기능 집합이다. 예) iOS SDK를 다운..
카라츠바의 빠른 곱셈 (Karatsuba algorithm)
카라츠바의 빠른 곱셈 알고리즘은 수백, 수만자리나 되는 큰 두개의 정수를 곱하는 알고리즘이다. 필요성 카라츠바 알고리즘을 소개하기에 앞서, 두자릿수 이상의 두 수를 곱하는 과정은 다음과 같다. 이 알고리즘의 시간복잡도는 두 정수의 길이가 모두 n이라고 할 때 O(n^2)이다. 2중 for문을 이용하고 있으니 이 점을 이해하기는 어렵지 않을 것이다. 카라츠바 알고리즘은 이 시간복잡도를 O(n^log(3)) 까지 낮춰주기 위해 사용된다. log(3) = 1.585...이므로 O(n^2) 보다 훨씬 적은 곱셈을 필요로 한다. 만약 n이 10만이라고 하면 곱셈 횟수는 대략 100배 정도 차이가 난다. 아이디어 자릿수가 n인 두개의 수 a,b를 단순히 곱하기 위해서는 O(n^2)이 소요되지만, 덧셈과 뺄셈을 하는..
아스키코드(ASCII Code) - 컴퓨터의 문자 처리 원리
컴퓨터가 이해하는 언어는 0과 1(1bit)이다. 2진수로 데이터를 처리한다. 컴퓨터는 전기신호를 받아들이므로 전기의 OFF, ON 두 가지 상태(0과 1)로 모든 걸 표현하기 때문이다. 0과 1의 두 가지 상태를 나타내는 단위를 bit라고 한다. 그러나 1bit만으로는 표현할 수 있는 게 0, 1 단 두 개뿐이니, 더 큰 수를 표현하기 위해 8개의 bit를 묶어서 1byte를 사용한다. 컴퓨터가 데이터를 저장하는 최소 단위가 바로 이 byte다. 1byte는 8개의 bit니까 2의 8제곱, 즉 0~255(256개)의 데이터를 저장할 수 있다. 중요한 것은 더 큰 수를 표현할 수 있게 되었더라도 컴퓨터가 인식하는 것은 숫자라는 점이다. 컴퓨터는 0과 1 이외에는 아무것도 인식할 수 없기 때문이다. 그렇다..
[C++] Dynamic Programming (동적계획법) / Top-Down (탑다운)과 Bottom-Up (바텀업) 방식
I. 다이나믹 프로그래밍 다이나믹 프로그래밍은 메모리를 적절히 사용하여 수행 시간 효율성을 비약적으로 향상시키는 방법이다. 이미 계산된 결과(작은 문제)는 별도의 메모리 영역에 저장하여 다시 계산하지 않도록 한다는 것이 핵심이다. 즉, 하나의 문제는 단 한 번만 풀도록 하는 알고리즘이다. (우리가 평소에 문제를 풀이할 때 효율적인 방법으로 고안할 필요가 있다.) 다이나믹 프로그래밍의 구현은 일반적으로 두 가지 방식(탑다운-하향식, 바텀업-상향식)으로 구성된다. 매우 비효율적인 문제더라도 다이나믹으로 획기적으로 시간을 줄일 수 있다. 다이나믹 프로그래밍은 조건을 만족해야 사용할 수 있다. 최적 부분 구조 - 큰 문제를 작은 문제로 나눌 수 있고, 작은 문제를 모아서 큰 문제를 해결 중복 부분 문제 - 동일..
탐욕 / 그리디 알고리즘 (Greedy Algorithm)
Greedy Algorithm 탐욕 알고리즘(그리디 알고리즘)은 특정 경우들 중 하나를 선택할 때, 그 순간에 가장 최적의 경우를 선택하는 알고리즘이다. 목적지까지 최단 경로로 가야 하는 상황을 예로 들어보자. 목적지를 향해 가던 중, 갈림길을 만났다. 그리디 알고리즘에서는, 다음과 같은 갈림길들 중 현재 상황에서만 최적인 경우를 선택한다. 따라서 위 그림에 그리디 알고리즘을 적용한다면, 직진을 하게 될 것이다. 하지만 만약 직진으로 간 다음 경유지에서 목적지까지의 거리가 100km이고, 다른 두 갈림길의 경유지에서 거리는 10km라면 어떻게 될까? 그리디 알고리즘을 통해 최적의 경우를 선택했지만, 결과적으로는 직진을 선택했기 때문에 목적지까지 최단경로로 갈 수 없게 된다. 이와 같이 그리디 알고리즘은 ..
[C++] 이분 탐색 (Binary Search)
이분 탐색(Binary search)이란? - 정렬된 리스트(배열)에서 원하는 값(target)의 존재 여부(존재 위치)를 찾는 알고리즘. - 반드시 리스트(배열)를 정렬해서 사용해야 한다는 단점이 있다. - 탐색할 때마다 검사 범위가 절반으로 줄어든다. - 재귀적인 방법, 반복문, STL를 이용하여 이분 탐색(Binary Search)을 실행할 수 있다. - Time Complexity : O(log N) 변수 설명 1. int low & int high 검사 범위의 시작점, 끝점의 인덱스를 가리키기 위한 변수. left는 시작점을, right를 끝점의 인덱스를 가리킨다. // nums에 수들이 들어가있다고 가정 vector nums; int low = 0; // 초기 세팅: 제일 앞 인덱스 int h..