#include <cstdio>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
/**
* https://www.acmicpc.net/problem/2504
* BOJ 백준온라인져지 2504 괄호의 값 풀이
*/
using namespace std;
int main(){
stack<char> characterList;
int integerList[31] = {1}; // index 0 은 1
char temp, compared, pre = '.';
// temp 는 string 에서 하나씩 뽑아서 쓴다.
// compared 는 ( or [ 가 들어가는데, 스택에서 빼서 쓴다.
// pre 는 이전 괄호를 체크한다. 곱셈의 결합법칙에 의해 (()()) 일때 둘러싼 괄호는 0으로 처리해준다.
char* string = new char[31]; // 입력 받을 string
scanf("%s", string);
int idx = 0, i = 0, length = strlen(string), tempInteger, result = 0;
// idx 는 integerList에 접근하기 위한 변수다. 괄호의 value 를 가져온다.
// i 는 string 에 저장된 문자를 뽑아쓰기 위한 변수
// length 는 string의 실제 길이
// tempInteger 는 integerList[idx] 를 빼서 저장한다.
// result 는 tempInteger들의 값을 더해서 답을 출력해주기 위한 변수다.
while(i != length){ // 마지막 문자가 아니라면 반복함
temp = string[i++]; // 하나씩 뽑는다
if(temp == '(' || temp == '['){ // 여는 괄호라면
idx++;
if(temp == '(')
integerList[idx] = 2 * integerList[idx-1];
if(temp == '[')
integerList[idx] = 3 * integerList[idx-1];
characterList.push(temp);
}else{ // 여는 괄호가 아니라면
if(characterList.empty()){ // 올바른 괄호가 아닐경우
result = 0;
break;
}
compared = characterList.top(), characterList.pop(); // 스택에 저장된것을 뽑는다.
tempInteger = integerList[idx--];
if(pre == ']' || pre == ')'){
tempInteger = 0;
}
if(compared == '(' && temp == ')'){
result += tempInteger;
}else if(compared == '[' && temp == ']'){
result += tempInteger;
}else{ // 올바른 괄호가 아닐경우
result = 0;
break;
}
}
pre = temp;
}
// 올바른 괄호가 아닐경우
if(characterList.size()) result = 0;
printf("%d", result);
return 0;
}
view raw BOJ_2504.cpp hosted with ❤ by GitHub

곱셈의 결합법칙을 이용해서 예외처리를 해줬다.


주석에 설명을 잘 달아놨다.

#include <cstdio>
#include <stack>
#include <vector>
/**
* https://www.acmicpc.net/problem/1874
* BOJ 백준온라인져지 1874 스택 수열 풀이
*/
using namespace std;
int main(){
stack <int> stack;
vector <char> vector; // 문자열 하기 위한 벡터
int N,temp=0; // temp는 c배열에 있는 값을 조회할때 사용한다.
int c[100000],idx=0; // c 배열에는 입력값을 차례대로 넣는다.
scanf("%d",&N);
while(N--) scanf("%d",&c[idx++]); // c배열에 넣는다.
for(int i = 0; i<idx; i++){
stack.push(i+1); // stack에 차례대로 1 2 3 4 넣는다.
vector.push_back('+'); // push는 +를 출력한다.
while(stack.size() && stack.top() == c[temp]) // stack top 값에 c[temp]가 있으면
stack.pop(), temp++, vector.push_back('-'); // 꺼내고 temp++ -출력
}
if(stack.size()) printf("NO"); // 스택에서 못 꺼낸값이 있으면 NO 출력
else{ // 아니면 vector에 들어있는 값을 차례대로 출력한다.
for(int i = 0, size = vector.size(); i<size; i++)
printf("%c\n",vector[i]);
}
return 0;
}
// class Node{
// public:
// int number;
// Node(int n);
// Node next;
// };
// Node::Node(int n){
// number = n;
// }
// class Stack{
// public:
// Node head;
// void push(int n);
// int pop();
// int size();
// private:
// int size = 0;
// };
// void Stack::push(int n){
// Node node = new Node(n);
// if(head != NULL){
// node.next = head;
// }
// head = node;
// size++;
// }
// int Stack::pop(){
// if(head == NULL) return -1;
// int number = head.number;
// head = head.next;
// size--;
// return number;
// }
// int Stack::size(){
// return size;
// }
view raw BOJ_1874.cpp hosted with ❤ by GitHub

처음에 문제를 잘 못 이해해서,

예제 입력 

8
4
3
6
8
7
5
2
1

이면

8 = n 이고

4번 +하고

4 - 3 + 1 만큼 -하고 이런식으로 되는 줄 알앗는데,


1~N까지 push하고 차례대로 pop해주는거였다.

아이디어 :

1. 에라토스테네스의 체를 이용해서 소수를 구한다.

2. 소수를 primeNumber에 하나씩 넣어준다. 마지막값은 0이다.

3. 2... 돌게되면 0이 나오는데 0이면 반복문을 종료한다.

4. 반복문 안에 반복문을 넣어서 값을 더해주고 맞으면 빼기한 값을 저장하고 그걸로 체크를한다.



더 좋은 방법.


어차피 빼기값을 최소로 구하는거니까. n/2부터 시작해서 하나씩 빼면서 맞는답이 나오면 바로 출력하면 더 빠르다.

이 방법을 사용하면 2번 과정이 없어진다.


더 좋은 방법을 사용한다면,

O(Nnlgn)이 될거같다.

#include <cstdio>
/**
* https://www.acmicpc.net/problem/9020
* BOJ 백준온라인져지 9020 골드바흐의 추측 풀이
*/
#define MAX 10001
int main(){
bool isPrime[MAX-1] = {};
for(int i=2; i<MAX; i++) isPrime[i]=true;
for(int i=2; (i*i)<MAX; i++){
if(isPrime[i]){
for(int j=i*i; j<MAX; j+=i) isPrime[j]=false;
}
}
int idx = 0;
int primeNumber[MAX-1] = {};
for(int i = 2; i<MAX; i++) if(isPrime[i]) primeNumber[idx++] = i;
int N;
scanf("%d",&N);
while(N--){
int n;
scanf("%d",&n);
int min = MAX, tempI = 0, tempJ = 0, result = 0;
for(int i = 0; i < idx && result < n; i++){
result = primeNumber[i];
for(int j = i; j < idx && result + primeNumber[j] <= n; j++){
if(result + primeNumber[j] == n){
int subtraction = primeNumber[j] - result;
if(min > subtraction){
min = subtraction;
tempI = i;
tempJ = j;
}
}
}
}
printf("%d %d\n",primeNumber[tempI],primeNumber[tempJ]);
}
return 0;
}
view raw BOJ_9020.cpp hosted with ❤ by GitHub


문제를 딱 보고.

아 이건! 미리 구해놓고 하나씩 출력하면 될듯~


에라토스테네스의 체를 복습했다.


#include <cstdio>
/**
* https://www.acmicpc.net/problem/4948
* BOJ 백준온라인져지 4948 베르트랑 공준 풀이
*/
int main(){
int N = 1;
bool isPrime[123456*2+1] = {};
for(int i=2; i<=123456*2; i++) isPrime[i]=true;
for(int i=2; (i*i)<=123456*2; i++){
if(isPrime[i]){
for(int j=i*i; j<=123456*2; j+=i) isPrime[j]=false;
}
}
while(1){
scanf("%d",&N);
if(N == 0) break;
int result = 0;
for(int i = N+1,length=2*N; i<=length; i++){
if(isPrime[i]) result++;
}
printf("%d\n",result);
}
return 0;
}
view raw BOJ_4948.cpp hosted with ❤ by GitHub

c++ 기본기 없이 코딩하려니 에러도 많이나서 질문도 많이했다.


풀이과정은

1. 무식하게 버블정렬 : 시간초과

2. sort를 사용하니까 통과됨


bool cmp(string a, string b){
if(a.length() < b.length()) return true;
else if(a.length() == b.length()) return a.compare(b) < 0;
return false;
}

a.length >= b.length를 고려 안해줘서 조금 많이 틀렸다.

#include <cstdio>
#include <vector>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
/**
* https://www.acmicpc.net/problem/1181
* BOJ 백준온라인져지 1181 단어 정렬 풀이
*/
using namespace std;
bool cmp(string a, string b){
if(a.length() < b.length()) return true;
else if(a.length() == b.length()) return a.compare(b) < 0;
return false;
}
int main(){
int N;
vector<string> v = vector<string>();
scanf("%d",&N);
while(N--){
char *temp = (char*)malloc(60);
scanf("%s",temp);
string t = string(temp);
if(find(v.begin(), v.end(), t) == v.end()){
v.push_back(t);
}
free(temp);
}
sort(v.begin(), v.end(), cmp);
for(int i = 0,size=v.size(); i<size; i++)
printf("%s\n",v[i].c_str());
return 0;
}
view raw BOJ_1181.cpp hosted with ❤ by GitHub

카운팅 정렬을 사용했다.


제공되는 숫자들의 절댓값이 4000을 넘지 않는다.

-4000 <= x <= 4000 

idx는 0부터 시작하니까 4000 을 더해주면 0 ~ 8000이다.

그럼 배열의 length 는 8001.


산술평균은 입력받는 값들을 합해서 N으로 나눠주면 된다.

중앙값은 idx 0 부터 체크하면서 N / 2 번째의 숫자를 확인해주면 된다.

최빈값은 애매하게 2번째로 작은값을 출력을 하라고 한다.

처음에 최빈값이 몇개 나왔는지를 구하고, 2번째로 작은 값을 구해준다.

범위는 간단하게 제일 작은값을 min으로 넣어주고, 가장 큰 값을 max로 넣어서 max - min 해준다.

min과 max를 넣어주는 과정은 최빈값을 구하는 과정에서 list[i] > 0 이면 체크해서 넣어준다.

#include <cstdio>
#include <math.h>
/**
* https://www.acmicpc.net/problem/2108
* BOJ 백준온라인져지 9426 중앙값 측정 풀이
*/
#define MAX_LENGTH 8001
#define RoundOff(x, dig) (floor((x) * pow(10,dig) + 0.5) / pow(10,dig))
int main(){
int N,cnt,list[MAX_LENGTH] = {},idx,many[2]={},max=0,min=8000;
long long sum = 0;
scanf("%d", &N);
cnt = N;
while(cnt--){
scanf("%d",&idx);
sum+=idx, list[idx+=4000]++;
}
idx = 0;
for(int i = 0; i<MAX_LENGTH; i++){
if(many[0] < list[i]) many[0] = list[i], many[1] = i - 4000;
if(list[i]){
max = (max < i) ? i : max;
min = (min > i) ? i : min;
}
}
cnt = 0;
for(int i = 0; i<MAX_LENGTH; i++){
if(many[0] == list[i]){
if(cnt){
many[1] = i - 4000;
break;
}
cnt++;
}
}
for(int i = 0, length = N/2; i<=length; i++){
while(list[idx]==0) idx++;
list[idx]--;
}
printf("%.lf\n",roundf(sum/(double)N));
printf("%d\n",idx-4000);
printf("%d\n",many[1]);
printf("%d",max-min);
return 0;
}
view raw BOJ_9426.cpp hosted with ❤ by GitHub

KMP를 사용해서 풀었고,

LinkedList에 idx값을 담아줬다.


import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/1786
* BOJ 백준온라인져지 1786 찾기 풀이
*/
public class Main {
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static int pi[];
private static int N,M;
private static String str,pattern;
static{
try{
str = br.readLine();
pattern = br.readLine();
}catch(Exception e){
}
}
public static void main(String args[]) {
initPi(pattern);
LinkedList<Integer> list = KMP(pattern);
System.out.println(list.size());
for(int temp : list){
System.out.println(temp);
}
}
private static void initPi(String str){
char[] temp = str.toCharArray();
pi = new int[temp.length];
int j = 0;
for(int i = 1; i<temp.length; i++){
while (j > 0 && temp[i] != temp[j]) {
j = pi[j-1];
}
if(temp[i] == temp[j]){
pi[i] = ++j;
}
}
}
private static LinkedList<Integer> KMP(String s){
LinkedList<Integer> list = new LinkedList<>();
int cnt = 0, j = 0;
char A[] = str.toCharArray(), B[] = s.toCharArray();
for(int i = 0, length = str.length(); i<length; i++){
while (j > 0 && A[i] != B[j]){
j = pi[j-1];
}
if (A[i] == B[j]){
if (j == B.length-1){
j = pi[j];
list.add(i-B.length+2);
}else{
j++;
}
}
}
return list;
}
}
view raw BOJ_1786.java hosted with ❤ by GitHub


가장 큰 거

String을 그대로 사용하면 문자열 추가중에 시간초과가 남

StringBuilder를 사용하면 해결~


KMP는 더 공부가 필요함(PI를 구하는 쪽을 걍 넘어간듯)

import java.util.*;
import java.io.*;
/**
* https://www.acmicpc.net/problem/5525
* BOJ 백준온라인져지 5525 IOIOI 풀이
* 이슈 : StringBuilder를 사용하지 않으면 시간초과가 난다.
*/
public class Main {
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static int pi[];
private static int N,M;
private static String str;
static{
try{
N = lineToInt();
M = lineToInt();
str = br.readLine();
}catch(Exception e){
}
}
public static void main(String args[]) {
StringBuilder s = new StringBuilder("I");
for(int i = 0; i<N; i++){
s.append("OI");
}
initPi(s.toString());
System.out.println(KMP(s.toString()));
}
private static void initPi(String str){
char[] temp = str.toCharArray();
pi = new int[M];
int j = 0;
for(int i = 1; i<temp.length; i++){
while (j > 0 && temp[i] != temp[j]) {
j = pi[j-1];
}
if(temp[i] == temp[j]){
pi[i] = ++j;
}
}
}
private static int KMP(String s){
int cnt = 0, j = 0;
char A[] = str.toCharArray(), B[] = s.toCharArray();
for(int i = 0; i<M; i++){
while (j > 0 && A[i] != B[j]){
j = pi[j-1];
}
if (A[i] == B[j]){
if (j == B.length-1){
j = pi[j];
cnt++;
}else{
j++;
}
}
}
return cnt;
}
private static int lineToInt() throws IOException{
return Integer.parseInt(br.readLine());
}
}
view raw BOJ_5525.java hosted with ❤ by GitHub


1번째 풀이와 2번째 풀이가 있다.

1번째 풀이는 시간초과가 난다.

O(MN) = 16억번


2번째 풀이는

O(M)이다.


-1이 나오는 조건은 x가 N보다 크거나 같을때(스왑하는 과정이나 입력값이 이상할때)

정답을 구하는 방법은

앞 자리 즉 x 의 값으로 y 의 값을 찾아가는 형식이다.

M을 계속 더해줌

#include <cstdio>
/**
* https://www.acmicpc.net/problem/6064
* BOJ 백준온라인져지 6064 카잉 달력 풀이
*/
int lcm(int a, int b);
int gcd(int a, int b);
int main(){
int T;
scanf("%d", &T);
while(T--){
int M,N,x,y;
scanf("%d%d%d%d",&M,&N,&x,&y);
if(M > N){
int temp;
temp = N, N = M, M = temp;
temp = x, x = y, y = temp;
}
int _lcm = lcm(M,N);
if(x>=N) printf("-1\n");
else{
int result = x, tempy = x;
while(y!=tempy&&_lcm>result){
tempy += M;
result += M;
if(tempy > N) tempy %= N;
}
if(_lcm<result||(tempy!=y&&_lcm==result)) printf("-1\n");
else printf("%d\n",result);
}
}
return 0;
}
int gcd(int a, int b){
if(a == 0)
return b;
return gcd(b%a, a);
}
int lcm(int a, int b){
return a * b / gcd(a, b);
}
/* 첫 번째 풀이
int gcd(int a, int b){
if(a == 0)
return b;
return gcd(b%a, a);
}
int lcm(int a, int b){
return a * b / gcd(a, b);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int M,N,x,y,cnt = -1,tempx=0,tempy=0;
scanf("%d%d%d%d",&M,&N,&x,&y);
for(int i = 0, _lcm = lcm(M,N); i<_lcm; i++){
tempx = tempx % M + 1;
tempy = tempy % N + 1;
if(x == tempx && y == tempy){
cnt = ++i;
break;
}
}
printf("%d\n", cnt);
}
return 0;
}
*/
view raw BOJ_6064.cpp hosted with ❤ by GitHub

(tempy!=y&&_lcm==result)의 조건을 안넣어서 계속 틀렸었다.


(tempy!=y&&_lcm==result)를 넣지 않으면 거의다 lcm(M,N)의 값이 뜬다.

일단 문제를 보면 0~9까지의 숫자카드를 1세트로 계속 받고 6 = 9 이다.


그래서 9를 입력받으면 6배열에 ++해주고

for loop을 하면서 배열에 값을 하나씩 빼줬다.

6은 2개씩 빼줌


for문을 while문으로 감싼 이유는 1세트씩 계속 주기위해서.

#include <cstdio>
#include <cstring>
/**
* https://www.acmicpc.net/problem/1475
* BOJ 백준온라인져지 1475 방 번호 풀이 풀이
*/
#define MAX 1111111
#define LENGTH 10
int main(){
char str1[MAX];
int d[LENGTH] = {0}; // 0 ~ 9 {}를 안하면 쓰레기값이 들어가서 안됨
scanf("%s", str1);
for(int i = 0, length = strlen(str1); i<length; i++)
str1[i]=='9'?d[6]++:d[str1[i]-48]++;
int cnt = 0, loop = 1;
while(loop){
loop = 0, cnt++, d[6]--;
for(int i = 0; i<LENGTH-1; i++){
d[i]--;
if(d[i] > 0) loop = 1;
}
}
printf("%d", cnt);
return 0;
}
view raw BOJ_1475.cpp hosted with ❤ by GitHub

+ Recent posts