코딩테스트
코딩테스트 사이트
- 프로그래머스: 네이버, 카카오 등 IT 기업들의 코딩테스트 사이트
- solved.ac: 백준 온라인 저지를 단계별로 분류
- SW Expert Academy: 삼성 코딩테스트 사이트
- Softeer: 현대 자동차그룹 코딩테스트 사이트
이론
시간복잡도
- Time Complexity는 알고리즘의 성능을 나타내는 지표로 입력 크기에 따른 연산횟수의 추이를 활용
- 점근표기법인 Big-O Notation을 사용
공간복잡도
C++ 필수 문법
자료형
- 정수형(short, int, long long): short는 2bytes; int는 4bytes; long long은 8bytes
- 실수형(float, double): float는 4bytes; double은 8bytes
- 문자형(char)
- 논리형(bool)
- 형 변환
- 명시적 형 변환: (int)a, int(a), static_cast (a);
- 암시적 형 변환: 변수의 메모리 크기가 큰 쪽으로 타입 변환
- auto: 변수의 타입을 자동으로 추론
#include <iostream>
using namespace std;
int main(int argc, char** argv){
float a = 10.5f;
double b = 1.618;
auto pi = 3.141592; // double로 추론
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << static_cast<int> (a) << std::endl;
return 0;
}
연산자
- 산술 연산자: +(add), -(sub), *(mul), /(div), %(mod)
- 비교 연산자: ==(equal), !=(not equal), >(bigger), >=(equal or bigger), <(smaller), <=(equal or smaller)
- 논리 연산자: &&(and), ||(or), !(not),
- 비트 연산자: &(and), |(or), ~(not), ^(xor)
- 증감 연산자: ++a, a++, --a, a--
- 부호 연산자: +a, -a
- sizeof: 변수가 가리키는 데이터의 크기를 byte로 표현
문자열
- 문자(char)
- 문자열(string)
- 문자열 찾기: 해당 문자열이 시작하는 인덱스 반환, 찾기 못하면 string::npos 반환, O(N)
- find(찾으려는 문자열), find(찾으려는 문자열, 탐색 시작 위치)
- 문자열 추가, 수정
- 문자열 추가: + 연산자
- 문자열 수정: [] 연산자, replace(시작 위치, 문자 개수, 대체 문자열)
/* 문자열 초기화 */
std::string str1;
std::string str2 = "Hello";
std::string str3(str2, 0, 5); // 문자열 부분 복사(0번 시작, 5개 문자)
std::string str3(10, '*'); // 반복된 문자열 초기화
/* 문자열 찾기 */
std::string str = "Hello, C++ World!";
size_t pos1 = str.find("Hello");
std::cout << pos1 << std::endl;
size_t start_index = 2;
size_t pos2 = str.find("Hello", start_index);
std::cout << pos2 << std::endl;
/* 문자열 추가 */
std::string str = "Banana";
str += ", Carrot";
std::cout << str << std::endl;
/* 문자열 수정 */
str[2] = 'I';
std::cout << str << std::endl;
str.replace(1, 5, "all");
std::cout << str << std::endl;
제어문
- 조건문: if문, switch문, 중첩 조건문
- 반복문: for문, 범위 기반 for문, while문, do ~ while문, 중첩 반복문
- 반복 제어: continue(생략), break(탈출)
/* 조건문 */
if(조건문){
...
} else if (조건문) {
...
} else {
...
}
switch(변수){
case 값:
...
break
case 값:
...
break
default:
...
break
}
/* 반복문 */
for(초기식; 종료조건; 증감식){
...
}
for(auto 변수: 컨테이너){
...
}
while(조건){
...
탈출 조건
}
do {
...
탈출 조건
} while(조건);
/* 반복문 제어 */
for(초기식; 종료조건; 증감식){
...
if (조건)
break;
if (조건)
continue;
}
함수
- 함수 정의: 반환타입 함수명(매개변수1, ...)로 정의; 반환값이 없다면 void 사용
- 함수 호출: 인수를 매개변수에 전달하여 호출
- call by value: 함수에 값을 복사하여 전달, 데이터가 클 경우 복사 비용 문제
- call by address: 포인터를 사용하여 주소값을 전달; 주소값을 전달받은 변수의 주소와 실제 변수의 주소값이 다름
- call by reference: 참조자를 사용하여 변수 복사가 아닌 참조자를 통해 변수에 접근; 참조 변수와 참조 대상 변수의 주소값이 일치
void modify(int& var1){
var1 = 10;
std::cout << &var1 << std::endl;
std::cout << var1 << std::endl;
return;
}
int main(int argc, char** argv){
int val = 3;
std::cout << &val << std::endl;
std::cout << val << std::endl;
modify(val);
std::cout << val << std::endl;
return 0;
}
포인터 및 참조
- 포인터
- 참조
int a = 10; // 변수 선언 및 초기화
int* ptr = &a; // 포인터 선언 및 초기화
int& ref = a; // 참조자 선언 및 초기화
std::cout << ptr << std::endl; // 포인터가 가리키는 주소
std::cout << *ptr << std::endl; // 포인터가 가리키는 값
std::cout << ref << std::endl; // 참조가 가리키는 값
STL(Standard Template Library)
- STL: C++에서 제공하는 템플릿 기반의 표준 라이브러리
- 템플릿: 함수나 클래스를 구현할 때 어떤 타입에서도 동작할 수 있는 문법
- STL 구성: Container(데이터를 담을 공간), Iterator(컨테이너에 접근 및 순회), Algorithm(데이터 처리 및 제어)
- container를 for문에서 사용시 상수 레퍼런스 사용(비용문제)
- Iterator: 컨테이너의 종류에 관계없이 원소들을 순회하고 접근하도록 함; 순방향 반복자(begin(), end()), 역방향 반복자(rbegin(), rend())
- Container: 데이터를 저장하는 객체; vector, set, map, priority_queue, unordered_set, unordered_map
- Vector: 데이터를 순차적으로 저장하고 인텍스를 통해서 특정 위치의 원소에 쉽게 접근
#include <vector>
using namespace std;
int main(int argc, char** argv){
/* vector 선언 및 초기화 */
vector<int> v1;
vector<int> v2 = {1, 2, 3, 4};
vector<int> v3(4,3); // 벡터의 크기는 4이고 원소는 3으로 초기화
/* 2차원 배열 */
vector<vector<int>> v1;
vector<vector<int>> v2(rows, vector<int>(cols));
vector<vetor<int>> v3(rows, vector<int>(cols, val));
vector<vector<int>> v4 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
/* 원소 변경 */
vector<int> v = {1, 2, 3, 4, 5};
v[2] = 10;
/* 삽입과 삭제 */
v.insert(v.begin(), val);
v.erase(v.begin());
/* 맨 뒤에 삽입과 삭제 */
v.push_back(val);
v.pop_back();
}
- set: 중복을 허용하지 않고 저장된 데이터를 자동으로 정렬하는 컨테이너, 트리 구조로 정렬 상태 유지
#include <set>
using namespace std;
int main(int argc, char** argv){
/* set의 선언 및 초기화 */
set<int> s1;
set<int> s2 = {3, 1, 3, 2, 4};
set<int> s3(s2);
/* 원소 탐색: O(logN) */
set<int> s = {1, 2, 3, 4, 5};
int targets[] = {3, 7};
for (auto target: targets){
auto it = s.find(target);
if (it != s.end()) {
std::cout << "find target: " << *it << std::endl;
} else {
std::cout << "XXX: " << *it << std::endl;
}
}
/* 삽입과 삭제: O(logN) */
set<int> s = {1, 3, 2, 1, 5};
s.insert(val);
s.erase(val);
auto it = s.find(val);
if (it != s.end()) {
s.erase(it);
}
return 0;
}
- map: 키와 값을 쌍으로 갖는 컨테이너. 키와 값의 쌍을 entry라고하며 std::pair 타입으로 표현. 내부는 균형 이진 트리로 구성. 키값을 기준으로 정렬. 키값은 중복되지 않고 유일함. O(logN)
#include <map>
int main(int argc, char** argv){
/* map 선언 및 초기화 */
map<string, double> m1;
map<string, double> m2 = {{"Apple": 1.5}, {"Banana": 1.0}};
/* 원소 접근 및 탐색: O(logN) */
int cost = m2["key"]; // 키가 없는 경우 0 반환
std:: cout << cost << std::endl;
auto it = m2.find("key");
if (it != m2.end()){
int cost = it->second;
std::cout << cost << std::endl;
}
/* 값 변경 */
m2["key"] = val // 값이 없다면 추가
/* 삽입과 삭제 */
map<string, double> m = {{"A": 10.0}, {"B": 13.2}, {"C": 15.1}, {"D": 0.9}};
m.insert(make_pair("key", val); // 인수로 pair객체를 받음, make_pair() 혹은 {}를 사용. O(logN)
m.insert({"key": val});
m["key"] = val;
for (const auto& item: m){
std::cout << m->first << " : " << m->second << std::endl;
}
m.erase("key");
auto it = m.find("key");
if (it != m.end()){
m.erase(it);
}
return 0;
}
- unordered_set: 해시 기반으로 데이터를 자동정렬하지 않음. 삽입, 삭제, 탐색이 O(1)
#include <unordered_set>
int main(int argc, char** argv){
/* unordered_set 선언 및 초기화 */
unordered_set<int> us;
/* 삽입 */
us.insert(val);
return 0;
}
- unordered_map: 해시 기반으로 데이터를 자동정렬하지 않음. 삽입, 삭제, 탐색이 O(1)
#include <unordered_map>
int main(int argc, char** argv){
/* 선언 및 초기화 */
unordered_map<string, int> um;
/* 삽입 */
um["key"] = val;
return 0;
}
STL 알고리즘
- count(시작 반복자, 끝 반복자, 확인할 값): 컨테이너 내에서 특정 값이 나타나는 횟수 세기. O(N)
- sort(시작 반복자, 끝 반복자); sort(시작 반복자, 끝 반복자, 비교함수): 컨테이너를 정렬하는 함수. 오름차순 정렬. O(NlogN)
- next_permutation(시작 반복자, 끝 반복자): 가능한 모든 순열을 생성, 생성 가능한 순열이 있다면 true, 없다면 false. O(N*N!)
- unique(시작 반복자, 끝 반복자): 컨테이너 내 중복되는 원소들을 뒤로 밀어내고 중복되지 않는 원소들만 남겨 새로운 범위의 끝 반복자를 반환. O(N)
- binary_search(시작 반복자, 끝 반복자, 찾을 값): 컨테이너에서 주어진 범위 내 원소에 이진 탐색을 수행. 탐색을 수행하고 원소가 있으면 true, 없으면 false. 데이터가 이미 정렬되어 있어야함. O(logN)
- max_element(시작 반복자, 끝 반복자), min_element(시작 반복자, 끝 반복자): 컨테이너 내에서 최댓값, 최솟값의 위치를 반환. O(N)
#include <iostream>
#include <vector>
#include <algorithm>
struct Point {
int x, y;
Point(int x, int y) : x(x), y(y) {}
};
bool compare(const Point& a, const Point& b){
if (a.x == b.x){
return a.y < b.y;
}
return a.x < b.x;
}
int main(int argc, char** argv){
vector<int> v = {1, 3, 5, 6, 2, 9, 5, 6, 6, 4};
/* 특정 값이 나타나는 횟수 세기 */
int ret = count(v.begin(), v.end(), 5);
std::cout << ret << std::endl;
/* 정렬하기 */
sort(v.begin(), v.end()); // 오름차순 정렬
for (const auto& ele: v){
std::cout << ele << std::endl;
}
sort(v.rbegin(), v.rend()); // 내림차순 정렬
for (const auto& ele: v){
std::cout << ele << std::endl;
}
vector<Point> points = {{3, 4}, {1, 2}, {3, 1}, {2, 5}};
sort(points.begin(), points.end(), compare);
for (const Point& p: points) {
std::cout << "(" << p.x << ", " << p.y << ")" << std::endl;
}
/* 순열 생성: 데이터의 순서대로 생성 */
vector<int> v = {1, 2, 3};
do {
for (int i : v) {
std::cout << i << ", ";
}
std::cout << std::endl;
} while(next_permutation(v.begin(), v.end()));
/* 함수 중복 처리: 중복된 원소는 뒤로 이동 */
vector<int> v = {1, 2, 2, 4, 4, 4, 4, 4, 3, 3, 3, 3};
auto new_end = unique(v.begin(), v.end());
// 중복된 원소를 제외하고 확인
for (auto it = v.begin(); it != new_end; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 전체 원소 확인
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
/* 이진 탐색 */
vector<int> v = {0, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << binary_search(v.begin(), v.end(), 3) << std::endl;
std::cout << binary_search(v.begin(), v.end(), 10) << std::endl;
/* 최댓값, 최솟값 위치 찾기 */
vector<int> v = {1, 5, 10, 15, -1, 24, 3};
auto max_val = max_element(v.begin(), v.end());
auto min_val = min_element(v.begin(), v.end());
std::cout << *max_val << std::endl;
std::cout << *min_val << std::endl;
return 0;
}
'코딩테스트 > 코딩 테스트 합격자 되기(C++편)' 카테고리의 다른 글
[코딩테스트] 해시 (0) | 2024.07.09 |
---|---|
[코딩테스트] 큐 (0) | 2024.07.09 |
[코딩테스트] 스택 (0) | 2024.07.09 |
[코딩테스트] 배열 / 연결리스트 (0) | 2024.07.09 |