문제

 

풀이

괄호 안에 존재하는 수를 괄호 바로 앞에 있는 수만큼 반복한 문자열로 만들 수 있고, 모든 괄호를 제거했을 때 문자열의 길이를 구하는 문제입니다.

처음에는 재귀를 통해서 문자열을 직접 구해서 해결했었는데

어떤분께서 게시글에 int 범위가 벗어난다는 의견을 제시해주셔서 다시 풀게 되었습니다. 아마 저는 틀렸겠지요... ㅠ

 

생각해보니 문자열을 직접 구할 필요가 없더라고요! 길이만 구하면 되니까요!

그래서 이번에는 스택으로 접근했습니다.

문제의 핵심은 괄호 안의 숫자를 k번 반복한다는 것입니다.

그러면 괄호 안의 숫자의 길이 * k가 스택에 들어가면 된다는거겠죠.

 

그러면 스택에는 숫자와 괄호를 구분할 필요가 생깁니다.

우선 숫자가 나온다면 다음 문자가 "(" 인지 확인해야 합니다.

다음 문자가 "("가 아니라면 스택에 1을 넣으시면 됩니다. (길이가 1인 문자열)

다음 문자가 "("이라면 반복에 활용되는 k에 해당되기 때문에 해당 숫자를 스택에 넣습니다.

 

다음은 괄호가 나왔을 경우입니다.

현재 위치가 "("이면 괄호 구분을 위해 스택에 -1을 넣습니다.

스택에는 양의 정수만 들어가기 때문에 이런 방식으로 숫자와 괄호를 구분할 수 있습니다.

 

현재 위치가 ")"이면 스택에 쌓여있는 문자열의 길이들을 더해주도록 합니다.

괄호 짝인 -1이 나올 때까지만 더해주시면 됩니다.

그리고 -1 바로 다음에 있는 수를 꺼내서 곱한 값을 스택에 다시 넣어줍니다.

그러면 3(8) = 888의 과정이 마무리된 것입니다.

-1이 열리는 괄호가 되겠고, 바로 다음에 있는 수가 3에 해당됩니다. 8은 당연히 -1이 나오기 전까지 더한 값들이 됩니다.

 

위 과정들이 모두 끝난다면 스택에는 문자열의 길이가 여러개 들어있을 것입니다.

그 숫자들을 모두 더해주시면 답을 구할 수 있습니다.

문제에는 수의 범위가 명시되어있지 않기 때문에 lnog long 자료형으로 출력해주도록 합니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <string>
#include <stack>
using namespace std;
typedef long long ll;
 
string str;
int N;
 
void func() {
    stack<ll> s;
    for (int i = 0; i < N; i++) {
        if (str[i] == '(') {
            s.push(-1);
        }
        else if (str[i] == ')') {
            ll sum = 0;
            while (1) {
                ll x = s.top();
                s.pop();
                if (x == -1break;
                sum += x;
            }
            ll tmp = s.top();
            s.pop();
            s.push(tmp * sum);
        }
        else if (i < N - 1 && str[i + 1== '(') {
            s.push((ll)(str[i] - '0'));
        }
        else s.push(1LL);
    }
 
    ll ret = 0;
    while (!s.empty()) {
        ret += s.top();
        s.pop();
    }
    cout << ret << '\n';
}
 
void input() {
    cin >> str;
    N = str.size();
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

www.acmicpc.net/problem/17299

 

17299번: 오등큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

emoney96.tistory.com/49

 

boj 17298 오큰수

www.acmicpc.net/problem/17298 17298번: 오큰수 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다. www.acmicpc.net 스..

emoney96.tistory.com

위의 문제와 같은 문제입니다.

오큰수는 오른쪽에 있는 자신보다 큰 수 중에 가장 왼쪽에 있는 수를 출력하는 문제이고, 

이 문제는 오른쪽에 있는 자신보다 등장횟수가 많은 수 중에 가장 왼쪽에 있는 수를 출력하는 문제입니다.

자신보다 큰 수 -> 자신보다 등장횟수가 많은 수 의 차이이며 풀이는 같습니다.

 

이 문제 역시 수열을 역순으로 탐색하였고,

list[i]를 스택에 넣기 전에 자신보다 등장횟수가 적은 값들을 모두 pop해줍니다.

 

스택이 비어있으면 -1, 아니면 top을 출력해주시면 됩니다.

 

 

[C++]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <stack>
using namespace std;
 
stack<int> s;
int list[1000001], num[1000001], ans[1000001];
int N;
 
void print() {
    for (int i = 1; i <= N; i++) {
        cout << ans[i] << ' ';
    }
 
    cout << '\n';
}
 
void func() {
    for (int i = N; i > 0; i--) {
        while (!s.empty() && num[list[i]] >= num[s.top()]) s.pop();
 
        if (s.empty()) ans[i] = -1;
        else ans[i] = s.top();
 
        s.push(list[i]);
    }
}
 
void input() {
    cin >> N;
    for (int i = 1; i <= N; i++) {
        cin >> list[i];
        num[list[i]]++;
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
    print();
 
    return 0;
}
cs

 

 

[Java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Stack<Integer> s = new Stack<>();
    static int list[], num[], ans[];
    static int N;
 
    static void print() {
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= N; i++)
            sb.append(ans[i]).append(" ");
        System.out.println(sb.toString());
    }
 
    static void func() {
        for (int i = N; i > 0; i--) {
            while (!s.isEmpty() && num[list[i]] >= num[s.peek()])
                s.pop();
 
            if (s.isEmpty())
                ans[i] = -1;
            else
                ans[i] = s.peek();
 
            s.push(list[i]);
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N + 1];
        num = new int[1000001];
        ans = new int[1000001];
 
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
            num[list[i]]++;
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
        print();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 15926 현욱은 괄호왕이야!!  (1) 2023.07.24
boj 21939 문제 추천 시스템 Version 1  (0) 2022.02.11
boj 9372 상근이의 여행  (0) 2021.02.09
boj 1158 요세푸스 문제  (0) 2021.02.09
boj 1918 후위 표기식  (0) 2021.02.05

www.acmicpc.net/problem/1918

 

1918번: 후위 표기식

첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 A~Z의 문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 *가 생략되는 등의 수식

www.acmicpc.net

입력은 중위 표기식으로 주어지고 후위 표기식으로 출력하는 문제입니다.

 

우선 A ~ Z까지의 문자는 바로 출력입니다.

'('는 스택에 바로 push하시면 되고

')'가 나오면 스택에 '('가 나올때까지 pop한 것을 출력해줍니다.

+, -가 나오면 자신보다 우선순위가 낮은 연산자가 없으므로 괄호를 만날때까지 pop한 것을 출력해줍니다.

*, /가 나오면 자신보다 우선순위가 낮은 +, -가 나오거나 괄호를 만날때까지 pop한 것을 출력해줍니다.

마지막에 남아있는 연산자를 모두 출력합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Stack<Character> s = new Stack<>();
    static char ch[];
 
    static void func() {
        for (char x : ch) {
            if ('A' <= x && x <= 'Z')
                sb.append(x);
            else if (x == '(')
                s.push(x);
            else if (x == ')') {
                while (s.peek() != '(')
                    sb.append(s.pop());
                s.pop();
            } else if (x == '+' || x == '-') {
                while (!s.isEmpty() && s.peek() != '(')
                    sb.append(s.pop());
                s.push(x);
            } else {
                while (!s.isEmpty() && (s.peek() == '*' || s.peek() == '/'))
                    sb.append(s.pop());
                s.push(x);
            }
        }
 
        while (!s.isEmpty())
            sb.append(s.pop());
 
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        ch = st.nextToken().toCharArray();
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 9372 상근이의 여행  (0) 2021.02.09
boj 1158 요세푸스 문제  (0) 2021.02.09
boj 1935 후위 표기식2  (0) 2021.02.05
boj 2493 탑  (0) 2021.02.04
boj 6416 트리인가?  (0) 2021.02.04

www.acmicpc.net/problem/1935

 

1935번: 후위 표기식2

첫째 줄에 피연산자의 개수(1 ≤ N ≤ 26) 가 주어진다. 그리고 둘째 줄에는 후위 표기식이 주어진다. (여기서 피연산자는 A~Z의 영대문자이며, A부터 순서대로 N개의 영대문자만이 사용되며, 길이

www.acmicpc.net

피연산자가 문자로 주어진 후위표기식이 입력으로 들어오면 이를 계산한 결과를 소수 둘째 자리까지 출력하는 문제입니다.

우선 피연산자에 대응하는 값은 alphabet 배열에 넣어서 alphabet[ch-'A']와 같이 사용하였습니다.

 

A ~ Z가 오면 스택에 대응하는 값을 넣고, 연산자가 오면 두개를 꺼내서 계산한 값을 스택에 넣었습니다.

마지막에 스택에 들어있는 값은 1개이므로 그것을 출력하면 됩니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Stack<Double> s = new Stack<>();
    static char ch[];
    static double alphabet[] = new double[26];
    static int N;
 
    static void func() {
        for (char x : ch) {
            if ('A' <= x && x <= 'Z')
                s.push(alphabet[x - 'A']);
            else if (x == '+') {
                double a = s.pop();
                double b = s.pop();
                s.push(b + a);
            } else if (x == '-') {
                double a = s.pop();
                double b = s.pop();
                s.push(b - a);
            } else if (x == '*') {
                double a = s.pop();
                double b = s.pop();
                s.push(b * a);
            } else {
                double a = s.pop();
                double b = s.pop();
                s.push(b / a);
            }
        }
 
        System.out.printf("%.2f\n", s.pop());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(br.readLine());
        ch = st.nextToken().toCharArray();
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            alphabet[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 1158 요세푸스 문제  (0) 2021.02.09
boj 1918 후위 표기식  (0) 2021.02.05
boj 2493 탑  (0) 2021.02.04
boj 6416 트리인가?  (0) 2021.02.04
boj 3190 뱀  (0) 2021.02.02

www.acmicpc.net/problem/2493

 

2493번: 탑

첫째 줄에 탑의 수를 나타내는 정수 N이 주어진다. N은 1 이상 500,000 이하이다. 둘째 줄에는 N개의 탑들의 높이가 직선상에 놓인 순서대로 하나의 빈칸을 사이에 두고 주어진다. 탑들의 높이는 1

www.acmicpc.net

탑 A의 왼쪽에 있는 탑들 중에서 탑 A보다 더 큰 높이의 탑들 중 가장 오른쪽의 탑의 위치를 구하는 문제입니다.

배열크기를 너무 높게잡으면 메모리초과까지 나올 수 있어서 초기에 배열크기를 잘 잡아야합니다.

N이 500000까지 들어오기때문에 N^2으로는 무조건 시간초과뜹니다

 

먼저 입력으로 주어지는 탑의 높이를 list에 저장하였고, 1번부터 N번까지 순회를 합니다.

 

스택에는 인덱스를 유지합니다.

i번 위치에서 스택이 비어있지 않고, list[top]이 list[i]보다 작을동안 pop을 해줍니다.

그 후에 스택이 비어있으면 0, 아니면 스택의 top을 출력하시면 됩니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package BOJ.data_structure;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Boj2493 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Stack<Integer> s = new Stack<>();
    static int list[];
    static int N;
 
    static void func() {
        for (int i = 0; i < N; i++) {
            while (!s.isEmpty() && list[s.peek()] < list[i])
                s.pop();
 
            if (s.isEmpty()) {
                s.push(i);
                sb.append("0 ");
            } else {
                sb.append(s.peek() + 1 + " ");
                s.push(i);
            }
        }
 
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N];
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 1918 후위 표기식  (0) 2021.02.05
boj 1935 후위 표기식2  (0) 2021.02.05
boj 6416 트리인가?  (0) 2021.02.04
boj 3190 뱀  (0) 2021.02.02
boj 2346 풍선 터뜨리기  (0) 2021.02.02

www.acmicpc.net/problem/4889

 

4889번: 안정적인 문자열

입력은 여러 개의 데이터 세트로 이루어져 있다. 각 데이터 세트는 한 줄로 이루어져 있다. 줄에는 여는 괄호와 닫는 괄호만으로 이루어진 문자열이 주어진다. 문자열의 길이가 2000을 넘는 경우

www.acmicpc.net

괄호가 주어지는대로 그리디하게 해결할 수 있는 문제입니다.

 

'{'가 주어지면 스택에 바로 push합니다.

'}'일때 스택이 비어있으면 ans에 1을 더하고 방향을 바꿔 '{'로 스택에 push합니다.

스택이 비어있지 않으면 pop을 해주면 됩니다.

 

이 과정을 반복한 후에 스택이 비어있지 않으면 '{'이 짝수개 남아있다는 말이 됩니다.

그래서 마지막에 s.size()/2를 더해주고 출력합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Stack<Character> s = new Stack<>();
    static char ch[];
    static int ans = 0;
 
    static void func() {
        for (char x : ch) {
            if (x == '{') {
                s.push(x);
            } else {
                if (s.isEmpty()) {
                    ans++;
                    s.push('{');
                } else
                    s.pop();
            }
        }
 
        ans += (s.size() / 2);
        sb.append(ans + "\n");
        ans = 0;
        while (!s.isEmpty())
            s.pop();
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        ch = st.nextToken().toCharArray();
    }
 
    public static void main(String[] args) throws Exception {
        for (int T = 1;; T++) {
            input();
            if (ch[0== '-')
                break;
 
            sb.append(T + ". ");
            func();
        }
        
        System.out.println(sb.toString());
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 11279 최대 힙  (0) 2021.01.31
boj 1927 최소 힙  (0) 2021.01.31
boj 2504 괄호의 값  (0) 2021.01.26
boj 6198 옥상 정원 꾸미기  (0) 2021.01.26
boj 1874 수택 수열  (0) 2021.01.25

www.acmicpc.net/problem/2504

 

2504번: 괄호의 값

4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다.  만일

www.acmicpc.net

작년에 특강들을때 풀었던 문제지만 기억이 가물가물했습니다..

 

먼저 괄호의 값이 결정되는 기준입니다.

1. () 의 값은 2이다.

2. [] 의 값은 3이다.

3. (X) 의 값은 2 * X이다.

4. [X] 의 값은 3 * X이다.

5. 괄호열 X와 괄호열 Y가 결합된 XY의 값은 X+Y이다.

 

입력이 ( ( ) ( ) ) 이런식으로 주어지면 2 * (2 + 2) = 8이라고 할 수 있는데

저는 2 * 2 + 2 * 2 = 8 의 방식으로 해결하였습니다.

 

변수는 답을 출력하는 ans와 중간 값을 나타내는 sum으로 2개를 사용하였습니다.

 

'(' / '['일 때 sum * 2 or sum * 3을 하고 push합니다.

')' / ']'일 때 연산을 수행하기 전에 먼저 괄호가 올바른 괄호열인지 확인해야합니다.

올바른 괄호열이 맞으면 바로 이전값이 여는 괄호일 경우에만 ans에 더해주고,

그 후에 sum / 2 or sum / 3을 하고 pop합니다.

올바른 괄호열이 아니면 0을 출력하고 return합니다.

 

모든 연산이 끝나고 스택이 괄호가 들어있으면 올바른 괄호열이 아니므로 0을 출력하고,

스택이 비어있으면 올바른 괄호열이므로 답을 출력합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Stack<Character> s = new Stack<>();
    static char ch[];
    static int ans, sum = 1;
 
    static void func() {
        for (int i = 0; i < ch.length; i++) {
            if (ch[i] == '(') {
                sum *= 2;
                s.push(ch[i]);
            } else if (ch[i] == '[') {
                sum *= 3;
                s.push(ch[i]);
            } else if (ch[i] == ')') {
                if (s.isEmpty() || s.peek() != '(') {
                    System.out.println(0);
                    return;
                }
 
                if (s.peek() == '(') {
                    if (ch[i - 1== '(')
                        ans += sum;
                    sum /= 2;
                    s.pop();
                }
            } else {
                if (s.isEmpty() || s.peek() != '[') {
                    System.out.println(0);
                    return;
                }
 
                if (s.peek() == '[') {
                    if (ch[i - 1== '[')
                        ans += sum;
                    sum /= 3;
                    s.pop();
                }
            }
        }
 
        if (!s.isEmpty())
            System.out.println(0);
        else
            System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        ch = st.nextToken().toCharArray();
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

 

'algorithm > data-structure' 카테고리의 다른 글

boj 1927 최소 힙  (0) 2021.01.31
boj 4889 안정적인 문자열  (0) 2021.01.26
boj 6198 옥상 정원 꾸미기  (0) 2021.01.26
boj 1874 수택 수열  (0) 2021.01.25
boj 17298 오큰수  (0) 2021.01.25

www.acmicpc.net/problem/6198

 

6198번: 옥상 정원 꾸미기

문제 도시에는 N개의 빌딩이 있다. 빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다. i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으

www.acmicpc.net

바라보는 방향이 오른쪽이고, 그 방향에 자신보다 크거나 같은 높이의 건물과 그 이후의 건물의 옥상은 볼 수 없습니다.

 

저는 순차탐색으로 스택에 높이와 인덱스를 넣어가며 비교하였습니다.

 

먼저 s.peek의 높이가 현재 높이보다 작거나 같으면 자신 이후의 건물을 볼 수 없으므로 pop을 해줍니다.

이때 pop을 해주면서 현재의 인덱스와 삭제할 건물의 인덱스 사이에 존재하는 번호의 갯수를 ans에 더해줍니다.

 

이 작업이 끝나고 스택에 값이 남아있으면 s.peek()부터 작은 순서대로 pop이 될 것입니다.

s.peek()이 가장 마지막에 있는 건물이기 때문에 고정값(pre)으로 하고 pop하는 건물의 인덱스와 pre의 차이만큼 더해줍니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Stack<int[]> s = new Stack<>();
    static int list[];
    static int N;
    static long ans;
 
    static void func() {
        for (int i = 0; i < N; i++) {
            while (!s.isEmpty() && s.peek()[0<= list[i]) {
                ans += (i - (s.peek()[1+ 1));
                s.pop();
            }
 
            s.push(new int[] { list[i], i });
        }
 
        int pre = N - 1;
        while (!s.isEmpty()) {
            ans += (pre - s.peek()[1]);
            s.pop();
        }
        
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 4889 안정적인 문자열  (0) 2021.01.26
boj 2504 괄호의 값  (0) 2021.01.26
boj 1874 수택 수열  (0) 2021.01.25
boj 17298 오큰수  (0) 2021.01.25
boj 4358 생태학  (0) 2021.01.25

 

www.acmicpc.net/problem/1874

 

1874번: 스택 수열

1부터 n까지에 수에 대해 차례로 [push, push, push, push, pop, pop, push, push, pop, push, push, pop, pop, pop, pop, pop] 연산을 수행하면 수열 [4, 3, 6, 8, 7, 5, 2, 1]을 얻을 수 있다.

www.acmicpc.net

스택에 1~N을 순서대로 push, pop 과정을 반복하면서 입력에 주어진 순서대로 pop을 할 수 있는지 출력하는 문제입니다.

 

아래의 예시를 이용하여 리뷰하겠습니다.

8
4
3
6
8
7
5
2
1

N = 8, list[] = {4, 3, 6, 8, 7, 5, 2, 1} 입니다.

 

push 1 -> s.peek = 1, list[idx] = 4 (s.peek != list[idx] 이므로 (+))

push 2 -> s.peek = 2, list[idx] = 4 (s.peek != list[idx] 이므로 (+))

push 3 -> s.peek = 3, list[idx] = 4 (s.peek != list[idx] 이므로 (+))

push 4 -> s.peek = 4, list[idx] = 4 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 3, list[idx] = 3 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 2, list[idx] = 6 (s.peek != list[idx] 이므로 다음 진행)

push 5 -> s.peek = 5, list[idx] = 6 (s.peek != list[idx] 이므로 (+))

push 6 -> s.peek = 6, list[idx] = 6 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 5, list[idx] = 8 (s.peek != list[idx] 이므로 다음 진행)

push 7 -> s.peek = 7, list[idx] = 8 (s.peek != list[idx] 이므로 (+))

push 8 -> s.peek = 8, list[idx] = 8 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 7, list[idx] = 7 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 5, list[idx] = 5 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 2, list[idx] = 2 (s.peek == list[idx] 이므로 (-)후에 idx++)

              s.peek = 1, list[idx] = 1 (s.peek == list[idx] 이므로 (-)후에 idx++)

 

여기서 8까지 push 완료하였고, 스택 안의 모든 숫자가 pop되었으므로 순서대로 출력해주시면 됩니다.

만약에 모든 push가 이루어졌는데 pop이 더이상 진행되지 못할 경우에는 NO를 출력해주셔야합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Stack<Integer> s = new Stack<>();
    static int list[];
    static int N;
 
    static void func() {
        int idx = 0;
        for (int i = 1; i <= N; i++) {
            s.add(i);
            sb.append("+\n");
            while (!s.isEmpty() && idx < N && s.peek() == list[idx]) {
                s.pop();
                sb.append("-\n");
                idx++;
            }
        }
        
        while(!s.isEmpty() && idx < N && s.peek() == list[idx]) {
            s.pop();
            sb.append("-\n");
            idx++;
        }
        if(!s.isEmpty()) {
            sb = new StringBuffer();
            sb.append("NO\n");
        }
        
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 2504 괄호의 값  (0) 2021.01.26
boj 6198 옥상 정원 꾸미기  (0) 2021.01.26
boj 17298 오큰수  (0) 2021.01.25
boj 4358 생태학  (0) 2021.01.25
boj 5639 이진 검색 트리  (0) 2021.01.24

www.acmicpc.net/problem/17298

 

17298번: 오큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

스택으로 구현할 수 있고, 시간초과에 주위해야하는 문제입니다.

자바에서는 출력만으로도 시간초과가 나올 수 있기때문에 반복적인 System.out.println 보다는

StringBuffer, StringBuilder, BufferedWriter 중에서 사용해야합니다.

 

우선 오큰수는 자신의 오른쪽에 있는 숫자들 중에서 자신보다 큰 수 중에 가장 왼쪽에 있는 수를 말합니다.

 

저는 이 문제를 해결하기 위해 수열의 역순으로 탐색을 하였습니다.

list[i]를 스택에 넣기 전에 자신보다 작은 값들을 전부 pop해준 후에 남아있는 스택의 top에 있는 값이 오큰수 입니다.

 

먼저 스택이 비어있다면 자신이 가장 큰 수이므로 -1입니다.

비어있지 않다면 스택의 top이 오큰수입니다.

 

이 값들을 StringBuffer에 다 append를 해준 후에 마지막에 sb.toString()을 출력해주시면 되겠습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Stack<Integer> s = new Stack<>();
    static int list[], ans[];
    static int N;
 
    static void print() {
        for (int i = 0; i < N; i++) {
            sb.append(ans[i] + " ");
        }
 
        System.out.println(sb.toString() + "\n");
    }
 
    static void func() {
        for (int i = N - 1; i >= 0; i--) {
            while (!s.isEmpty() && s.peek() <= list[i])
                s.pop();
 
            if (s.isEmpty())
                ans[i] = -1;
            else
                ans[i] = s.peek();
 
            s.add(list[i]);
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N];
        ans = new int[N];
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
        print();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 6198 옥상 정원 꾸미기  (0) 2021.01.26
boj 1874 수택 수열  (0) 2021.01.25
boj 4358 생태학  (0) 2021.01.25
boj 5639 이진 검색 트리  (0) 2021.01.24
boj 1991 트리 순회  (0) 2021.01.22

+ Recent posts