Algorithm 공부 책: DoIt 알고리즘 코딩테스트 C++편
#include <iostream>
using namespace std;
#include <vector>
int main() {
vector<int> A;
A.push_back(1);//마지막에 1추가
A.insert(A.begin(), 7); //맨 앞에 7 삽입
A.insert(A.begin() + 2, 5);
A[4] = 5; //값변경
A.pop_back(); //마지막 값 삭제
A.erase(A.begin() + 3);
A.clear(); //모든 값 삭제
A.size(); //A의 크기 구하기
A.front(); //A의 처음값
A.back(); //마지막 값
A.at(5); //index5에 해당하는 값
A.begin(); //첫번째 데이터 위치
A.end(); //마지막 데이터의 다음위치
}
#include <iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
int main() {
int N;
string numbers;
cin >> N;
cin >> numbers;
int sum = 0;
for (int i = 0; i < numbers.length(); i++) {
sum += numbers[i] - '0';
}
cout << sum;
return 0;
}
#include <iostream>
using namespace std;
#include <vector>
int main() {
int N=0;
cin >> N;
vector <int> score(N);
int max = 0;
double mean = 0;
for (int i = 0; i < N; i++) {
cin >> score[i];
if (max < score[i]) max = score[i];
}
for (int j = 0; j < N; j++) {
mean+= (double)score[j] / max * 100;
}
cout << mean/N;
return 0;
}
#include <iostream>
using namespace std;
#include <vector>
int main() {
//C와 C++ 입출력 버퍼의 동기화
//false -> 동기화를 비활성화 -> 불안정하지만 속도 향상
ios::sync_with_stdio(false);
//입출력 버퍼를 비움으로써 성능향상
cin.tie(NULL);
cout.tie(NULL);
int suNo, quizno;
cin >> suNo >> quizno;
int S[100001] = {};
for (int i = 1; i <= suNo; i++) {
int temp;
cin >> temp;
S[i] = S[i - 1] + temp;
}
for (int i = 0; i < quizno; i++) {
int start, end;
cin >> start >> end;
cout << S[end] - S[start - 1] << "\n";
}
return 0;
}
문제: 백준문제 바로 보러가기
원리
구간합을 만들 때 원배열(1,1)부터 (x,y)까지의 직사각형 안에 들어있는 숫자들의 합을 dp(x,y)에 넣는다
파란색 구간의 합= dp(x2,y2)-dp(x1-1,y2)-dp(x2,y1-1)+dp(x1-1,y1-1)

#include <iostream>
using namespace std;
#include <vector>
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N,M;
cin >> N >> M;
vector<vector<int>> A(N + 1, vector<int>(N + 1, 0));
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
int temp;
cin >> temp;
if (i == 1 && j == 1) A[i][j] = temp;
else if (i == 1) A[i][j] = A[i][j - 1] + temp;
else if (j == 1) A[i][j] = A[i - 1][j] + temp;
else A[i][j] = A[i][j - 1] + A[i - 1][j] - A[i - 1][j - 1] + temp;
}
}
for (int i = 0; i < M; i++) {
int x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
cout << A[x2][y2] - A[x1-1][y2] - A[x2][y1-1] + A[x1-1][y1-1]<<"\n";
}
return 0;
}
문제를 통해 투 포인터 개념을 알아보자

#include <iostream>
using namespace std;
#include <vector>
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
int pos1 = 1; int pos2 = 1;
int sum = 1;
int cnt = 1;
while (pos2 != N) {
if (sum == N) {
cnt++;
pos2++;
sum = sum + pos2;
}
else if (sum > N) {
sum = sum - pos1;
pos1++;
}
else {
pos2++;
sum = sum + pos2;
}
}
cout<< cnt<< "\n";
return 0;
}
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int a, b;
cin >> a;
cin >> b;
vector <int> num(a, 0);
//입력받기
for (int i = 0; i < a; i++) {
cin >> num[i];
}
//오름차순 정렬
sort(num.begin(), num.end());
int i=0, j=a-1; int cnt = 0;
while (i < j) {
if (num[i]+num[j]==b) {
cnt++;
i++; j--;
}
else if (num[i] + num[j] > b) {
j--;
}
else {
i++;
}
}
cout << cnt;
return 0;
}
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
int main() {
int N;
cin >> N;
vector <int> num(N, 0);
for (int i = 0; i < N; i++) {
cin >> num[i];
}
sort(num.begin(), num.end());
int i,j;
int cnt = 0;
for (int w = 0 ; w < N; w++) {
int want = num[w];
i = 0; j = N - 1;
while (i < j) {
if (i == w) {
i++;
continue; //스스로를 포함하는 것을 제외
}
if (j == w) {
j--;
continue; //스스로를 포함하는 것을 제외
}
if(num[i] + num[j] == want) {
cnt++;
break;
}
else if (num[i] + num[j] > want) {
j--;
}
else {
i++;
}
}
}
cout << cnt ;
return 0;
}
두개의 포인터로 범위 지정한 다음
범위(window)를 유지한 채로 이동(sliding)하며 문제를 해결
투포인터와 비슷
#include <iostream>
using namespace std;
#include <vector>
int S, P;
int myarr[4];
int checkarr[4];
int checked = 0;
int res = 0;
void Add(char c);
void Remove(char c);
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
//입력받기
cin >> S >> P;
string str;
cin >> str;
for (int i = 0; i < 4; i++) {
cin >> checkarr[i];
if (checkarr[i] == 0) checked++; **//만약 0인경우 이미 조건 성립 -> checked++**
}
//초기문자열보내기
for (int i = 0; i < P; i++) {
Add(str[i]);
}
if (checked == 4) res++;
**//슬라이딩 윈도우 처리**
for (int i = P; i < S; i++) {
int j = i - P;
Add(str[i]);
Remove(str[j]);
if (checked == 4) {
res++;
}
}
cout << res;
return 0;
}
void Add(char c) {
switch (c){
case 'A':
myarr[0]++;
if (myarr[0] == checkarr[0]) checked++;
break;
case'C':
myarr[1]++;
if (myarr[1] == checkarr[1]) checked++;
break;
case 'G':
myarr[2]++;
if (myarr[2] == checkarr[2]) checked++;
break;
case 'T':
myarr[3]++;
if (myarr[3] == checkarr[3]) checked++;
break;
}
}
void Remove(char c) {
switch (c) {
case 'A':
if (myarr[0] == checkarr[0]) checked--;
myarr[0]--;
break;
case'C':
if (myarr[1] == checkarr[1]) checked--;
myarr[1]--;
break;
case 'G':
if (myarr[2] == checkarr[2]) checked--;
myarr[2]--;
break;
case 'T':
if (myarr[3] == checkarr[3]) checked--;
myarr[3]--;
break;
}
}
슬라이딩 윈도우 처리!!
→ 뒷문자열 하나씩 추가하고 맨 앞문자열 하나씩 제거하고,
→ 하나씩 옮겨질 때마다 checked==4가 되는지 확인하여 문자열이 정답에 해당하는지 아닌지 확인
초기 상태 checked !!
만약 checkarr[i]가 0이라면, 해당 문자는 따로 체크하지 않아도 조건을 이미 만족.
하지만 현재는 Add()가 호출되기 전에는 checked를 갱신하지 않기 때문에 이 경우를 놓칠 수 있음
⇒ 초기 상태에서 checkarr가 0인 항목은 checked++로 갱신시켜놔야함!
→ pass
문제: 백준 문제 보러가기
코드
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
vector <int> wantarr(N, 0);
vector <char> resarr;
stack <int> mystack;
bool yes = true;
//배열 입력
for (int i = 0; i < N; i++) {
cin >> wantarr[i];
}
int pop_cnt = 0; //pop을 몇번 했는지
int num = 1; //오름차순 해야함
for(int i=0;i<N;i++){
while (wantarr[i] >= num) {
mystack.push(num++);
resarr.push_back('+');
}
if (wantarr[i] == num) {
mystack.pop();
resarr.push_back('-');
}
else if(wantarr[i] < num){
if (**!mystack.empty()** && mystack.top() == wantarr[i]) {
mystack.pop();
resarr.push_back('-');
}
else {
cout << "NO";
yes = false;
break;
}
}
}
if (yes) {
for (int i = 0; i < resarr.size(); i++) {
cout << resarr[i] << "\n";
}
}
return 0;
}
문제 백준문제보러가기
코드 → 스택 이용
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main() {
int N;
cin >> N;
vector <int> inarr(N, 0);
vector <int> outarr(N, 0);
for (int i = 0; i < N; i++) {
cin >> inarr[i];
}
stack <int> st; //출력할 스택
for (int i = 0; i < N; i++) {
int f = inarr[i];
int o = 0;
if (i == N - 1) {
st.push(-1);
break;
}
for (int j = i + 1; j < N; j++) {
if (f < inarr[j]) {
o = inarr[i];
st.push(inarr[j]);
break;
}
}
if (o == 0) {
st.push(-1);
}
}
for (int i = 0; i <N; i++) {
outarr[i] = st.top();
st.pop();
}
for (int i = N-1; i >=0 ; i--) {
cout << outarr[i] << " ";
}
return 0;
}
정답 코드
내가 짠 것보다 더 효율적이라고 생각
내가 짠 코드에서는 마지막에 outarr를 reverse 시키기 위한 for반복문이 들어가는데, 이 정답코드는 그런 과정을 거치지 않음!
정답코드의 핵심
stack에 배열의 값이 아닌 배열의 인덱스를 push
인덱스를 이용해 값을 비교하는 것이 포인트!
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
vector <int> inarr(N, 0);
vector <int> outarr(N, 0);
for (int i = 0; i < N; i++) {
cin >> inarr[i];
}
stack <int> st; //출력할 스택
st.push(0);
//핵심 코드!
for (int i = 1; i < N; i++) {
while (!st.empty() && inarr[st.top()] < inarr[i]) {
outarr[st.top()] = inarr[i];
st.pop();
}
st.push(i);
}
while (!st.empty()) {
outarr[st.top()] = -1;
st.pop();
}
for (int i = 0; i < N; i++) {
cout << outarr[i] << " ";
}
return 0;
}
문제: 백준문제보러가기
코드
front()는 제거하는 역할이 아니라 front에 있는 값을 알려만 주기 때문에, front() → pop()을 같이 해줘야함#include <iostream>
#include <queue>
using namespace std;
int main() {
int N;
cin >> N;
queue<int> q;
for (int i = 1; i <= N; i++) {
q.push(i);
}
while (q.size() > 1) {
q.pop();
q.push(q.front());
q.pop();
}
cout << q.front();
return 0;
}
자신이 직접 우선순위를 정할 때는 구조체를 생성해야함
priority_queue는 "true를 반환하는 값이 먼저 오도록 정렬"
즉, a > b이면 a가 b보다 우선순위가 낮음을 의미합니다.
a=5 b=3 → 5>3 true → 3이 더 높은 우선순위
a=2 b=4 → 2>4 false → 2가 더 높은 우선순위
struct cmp{
bool operator()(int a, int b){
return a>b; //작은값이 더 높은 우선순위
}
}
#include <queue>
priority_queue<int, vector<int>, cmp>;// 루트가 최소값인 우선순위 큐 선언
#include <iostream>
#include <queue>
using namespace std;
struct compare{
bool operator()(int a, int b) {
int first = abs(a);
int last = abs(b);
//절댓값이 같으면 음수가 우선순위가 높음
if (first==last) {
return a > b;
}
//절댓값이 작은 수가 우선순위가 높음
else {
return first > last;
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
priority_queue<int, vector<int>, compare> q;
for (int i = 0; i < N; i++) {
int temp;
cin >> temp;
if (temp == 0) {
if (q.empty()) {
cout << 0 << '\n';
}
else {
cout << q.top() << '\n';
q.pop();
}
}
else {
q.push(temp);
}
}
return 0;
}