c++ 알고리즘

손현수·2023년 9월 13일
0

아스키코드 (ASCII)

  • 대표적인 알파벳의 아스키코드 값: A(65), Z(90), a(97), z(122), 0(48)
  • 대문자를 소문자로, 소문자를 대문자로
    str = "aBcDe";
    for(int i = 0; i < str.length(); i++) {
        if (str[i] > 90) str[i] = str[i] - 32;
        else str[i] = str[i] + 32;
    }

    for(int i = 0; i < str.length(); i++) {
        if (str[i] > 90) str[i] = tolower(str[i]);
        else str[i] = toupper(str[i]);
    }
    
    cout << str << endl;

벡터 관련 함수

vector의 시작, 끝 원소

vector<int> v;

v.front();	//첫번째 원소
v.back();	//마지막 원소

vector의 특정 원소 지우는 법

v.erase(v.begin() + 3) // v[3] 삭제
v.erase(v.begin() + 2, v.begin() + 5); // v[2]부터 v[4]까지 삭제
v.pop_back(); // 벡터의 마지막 원소 제거

string 또는 vector의 끝에 새로운 원소를 추가하는 방법

  • push_back() 메소드 사용, push_back()으로 string에 새로운 원소를 추가할 때는 char 타입의 원소를 추가해야 함. string에 string을 추가할 때는 단순 덧셈을 사용하거나 append() 메소드를 사용하면 됨.

vector와 string의 길이

  • string은 length, vector는 size
  • 이차원 벡터에서 행의 개수는 arr.size(), 열의 개수는 arr[0].size()

벡터에서 최솟값, 최댓값 찾기

  • algorithm 헤더를 추가해야 함.
int min = *min_element(v.begin(), v.end()); // v벡터의 최솟값 저장
int max = *max_element(v.begin(), v.end()); // v벡터의 최댓값 저장

int max_index = max_element(v.begin(), v.end()) - v.begin(); 
// 인덱스 값을 알 수도 있음

벡터에서 원소 찾기

  • algorithm 헤더 추가
vector<int> v = {2,35,6,6,6,7};

int count = count(v.begin(), v.end(), 6); // v 벡터에 있는 6의 개수

if (find(v.begin(), v.end(), 찾는값) == v.end()) 
	cout << "찾는 값이 없음" << endl;
    // find의 반환 값이 벡터의 끝이면 없는 거고 끝이 아니면 있는 것
    // 내가 찾는 값이 있을 때 그 원소의 인덱스를 계산하는 방법은
    // index = find(v.begin(), v.end(), 찾는값) - v.begin();

벡터 오름차순, 내림차순 정렬

  • algorithm 헤더 추가
vector<string> v = {"aver", "greg", "gwqaerff"};

sort(v.begin(), v.end()); // 오름차순
sort(v.rbegin(), v.rend()); // 내림차순

벡터의 길이를 지정하고 일괄적으로 초기화하는 방법

vector<int> v(52, 0); // 길이가 52인 벡터를 모두 0으로 초기화

벡터에서 중복값을 삭제하기

  • unique(벡터.begin(), 벡터.end()) 함수 호출 후 erase(시작 위치, 끝 위치) 함수를 호출하면 된다
    • unique() 함수 호출 시 벡터에서 중복된 값을 벡터의 뒤로 보내어 쓰레기 값으로 처리한 후 쓰레기 값이 시작되는 위치를 반환한다
    • 이때 쓰레기 값의 시작 위치부터 벡터의 종료 위치까지 erase()를 해주면 쓰레기값이 모두 없어지게 된다
vector<int> v = {1,1,1,2,3,3,3,4};
v.erase(unique(v.begin(), v.end()), v.end());
cout << v << endl;	// 1,2,3,4

형변환

형변환

  • string -> int: stoi(str) 메소드 사용
  • string -> unsigned long long: stoull(str) 메소드 사용
  • int -> string: to_string(num) 메소드 사용
  • int -> char: '0'을 더해주면 된다. (3 + '0': 정수 3을 '3'으로 변환)
  • char -> int: '0'을 빼주면 된다.

문자열 관련 함수

문자열 또는 문자끼리의 비교

  • s1 문자열이 s2와 같은지 비교할 때 s1.compare(s2) == 0이면 같은 문자열이고 아니면 다른 문자열이다.
  • 문자열 s1의 특정 문자가 'a'와 같은지 비교할 때는 s1[idx] == 'a'와 같이 비교하면 된다.

문자열에서 특정 문자 삭제하기 (erase 함수)

  • erase(시작 인덱스, 끝 인덱스): 시작인덱스부터 끝인덱스 - 1까지의 문자 삭제
string a = "i like you";
strting a = a.erase(0, 2);	//like you

일정 길이의 문자열 자르기

  • substr() 메소드 사용
string str = "Hello world";

string str1 = str.substr(0, 3); // str의 0번 인덱스부터 길이 3의 문자열
string str2 = str.substr(3); // str의 3번 인덱스부터 문자열의 끝까지

문자열 뒤집기

  • algorithm 헤더 추가
string s = "gawefa";

reverse(s.begin(), s.end());

문자열 공백 기준으로 자르기

#include <sstream>

string x, y, z;
string s = "abc def ghi";
stringstream ss(s);
string s1;

ss >> x >> y >> z;

while (ss >> s1) {
	cout << s1 << endl;
} // 문자열이 얼마나 긴지 모를 때 반복문을 활용할 수 있다.

제곱수

제곱 수 구하기

  • cmath 헤더 추가하기
int num = pow(10, 3); // 10의 세제곱
double num = sqrt(숫자); // 숫자의 제곱근

map 관련 함수

map에 새로운 원소 추가 및 원소 찾기

map<string, int> m; // 선언
map<string, int> m1 = {
	{'a', 1}, {'b', 2}
}	//선언 및 초기화

m.find(찾는 값) != m.end(); // 찾는 값이 존재하는 경우
m.find(찾는 값) == m.end(); // 찾는 값이 존재하지 않는 경우

map의 값 변경하기

map<string, int>m;
m["a"] = 10;
m["a"] += 5;
cout << m["a"] << endl;	//15

map + 범위기반 for문

map<string, int> m = {
    {"Re", 0}, {"Pt", 0}, {"Cc", 0}, {"Ea", 0}, {"Tb", 0}, {"Cm", 0}, {"Ex", 0}
};

for (auto i = m.begin(); i != m.end(); i++) {
	cout << i->first << ' ' << i->second << endl;
}

기타

  • map은 선언하면 자동으로 초기화가 수행된다. 따라서 mp[c]++과 같이 반복문을 순회하면서 값을 증가시키는 것이 가능하다.

stack 관련 함수

#include <stack>

stack<int> st;
stack<int> st2;

st.push();	// 원소 추가
st.pop();	// 제일 위의 원소 제거
st.top();	// 제일 위의 원소 반환
st.empty();	// 스택이 비어있으면 true 반환
st.size();	// 스택의 크기 반환
swap(st, st2); //두 스택의 내용을 바꿈

set 관련 함수

#include <set>

set<int> s;
    
s.insert(1);
s.insert(4);
s.insert(2);
    
for (auto it = s.begin(); it != s.end(); ++it) {
	cout << *it << ' ';
}

s.begin();
s.end();
s.erase(1);
s.count(1);	//1이 집합에 있으면 1 반환, 없으면 0 반환
s.empty();
s.size();
s.clear();

입력받기

공백 기준 입력을 하나의 문자열로 가져오기

string s;
getline(cin, s);
  • 주의할 점: 첫째줄에 5을 입력받고 둘째줄에 공백 기준 입력값이 존재할 때, 다음과 같이 코드를 작성할 경우 getline이 제대로 작동하지 않음
int n;
cin >> n;
string s;
getline(cin, s);
  • 제대로 작동하지 않는 이유: 첫째줄에서 정수를 입력할 때 누를 엔터(\n)가 getline으로 들어가기 때문에 제대로 된 입력이 이루어지지 않음. 이를 방지하기 위해서는 cin으로 정수를 입력받은 후 입력 버퍼를 비워줘야 한다.
  • cin으로 입력 받은 후 cin.ignore()를 호출하여 버퍼를 비워주고 getline()을 사용하자
int n;
cin >> n;
cin.ignore();
string s;
getline(cin, s);

큰 수에 대한 2의 거듭제곱 계산

1ULL과 비트 연산을 통해서 계산한다

#define ull unsigned long long

int main() {
	ull n;
    cin >> n;
    for (int i = 0; i < 10; i++) {
    	cout << n / (1ULL << i);
    }
}

두 수의 최대공약수 구하는 코드

int a = 24;
int b = 18;

while(b != 0) {
	int temp = a % b;
    a = b;
    b = temp;
}

return a;

위의 코드를 실행하면 결과적으로 a에 최대공약수가 할당되는 것을 알 수 있다.

조합 계산

어려운 문제에서는 꽤 큰 수에 대한 조합을 계산해야 하기 때문에 오버플로우를 방지하려면 미리 약분하며 계산하는 코드가 필요하다.

#define ULL unsigned long long

ULL combination(int n, int k) {
    if (k > n) return 0;
    if (k > n - k) k = n - k;

    ULL res = 1;

    for (int i = 1; i <= k; i++) {
        res = res * (n - k + i) / i;
    }

    return res;
}
profile
안녕하세요.

0개의 댓글