java의 Stack 클래스는 Vector를 상속받아 구현되었다
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class P10828 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] stack = new int[10000];
int c=0;
int cnt=0;
while(n-->0) {
String inStr = br.readLine();
if(inStr.charAt(1)=='u') {
StringTokenizer st = new StringTokenizer(inStr," ");
inStr = st.nextToken();
c = Integer.parseInt(st.nextToken());
}
if(inStr.equals("push")) {
stack[cnt++]=c;
} else if(inStr.equals("pop")) {
if(cnt==0) {System.out.println(-1); continue;}
System.out.println(stack[--cnt]);
} else if(inStr.equals("size")) {
System.out.println(cnt);
} else if(inStr.equals("empty")) {
if(cnt==0) {System.out.println(1);}
else {{System.out.println(0);}}
} else if(inStr.equals("top")) {
if(cnt==0) {System.out.println(-1); continue;}
System.out.println(stack[cnt-1]);
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Stack;
public class P10773 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<Integer> stack = new Stack<>();
int result=0;
for(int i=0;i<n;i++) {
int k = Integer.parseInt(br.readLine());
if(k==0) {stack.pop(); continue;}
stack.add(k);
}
Iterator<Integer> iter = stack.iterator();
while(iter.hasNext()) {result+= iter.next();}
System.out.print(result);
}
}
입력받은 수 stack에 push
0 나오면 직전에 받았던 숫자 pop
: Last In을 빼야하는 문제이므로 stack 활용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class P1874 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
int in =1; int result=0;
Stack<Integer> stack = new Stack<>();
for(int i=0;i<n;i++) {
int k = Integer.parseInt(br.readLine());
if(stack.empty()) {
while(in<=k) {stack.add(in++); sb.append('+');}
stack.pop(); sb.append('-');
continue;
}
if(k>stack.peek()) {
while(k>stack.peek()){stack.add(in++); sb.append('+');}
stack.pop(); sb.append('-');
} else if(k<stack.peek()) {
result=1;
break;
} else {
stack.pop(); sb.append('-');
}
}
if(result==1) {
System.out.println("NO");
} else {
for(int i=0;i<sb.length();i++) {
System.out.println(sb.charAt(i));
}
}
}
}
1. 반드시 오름차순으로 정수를 push하므로,
요구받은 수열이 스택의 최상단보다 작으면 불가능한 수열로 판단함2. 요구받은 수열이 스택의 최상단보다 크면 해당 수열까지 push한 후 pop
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class P9012 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<Character> stack = new Stack<>();
for(int i=0;i<n;i++) {
String result="YES";
String str = br.readLine();
for(int j=0;j<str.length();j++) {
if(str.charAt(j)=='(') {stack.add('(');}
else {
if(stack.empty()) {result="NO"; continue;}
stack.pop();
}
}
if(!stack.empty()) {result="NO";}
System.out.println(result);
stack.clear();
}
}
}
- ( 는 무조건 push
- )는 pop
-> )를 만났을때 스택이 비어있다면 or 전부 수행한 후에 스택이 비어있지 않으면 : not valid
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class P17413 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
StringBuilder sb = new StringBuilder();
int in =0;
Stack<Character> stack = new Stack<>();
for(int i=0;i<str.length();i++) {
switch (str.charAt(i)) {
case '<' :
while(!stack.empty()) {sb.append(stack.pop());}
in=1;
sb.append('<');
break;
case '>' :
in=0;
sb.append('>');
break;
case ' ' :
while(!stack.empty()) {sb.append(stack.pop());}
sb.append(' ');
break;
default :
if(in==1) {sb.append(str.charAt(i));}
else {stack.add(str.charAt(i));}
}
}
if(!stack.empty()) {while(!stack.empty()) {sb.append(stack.pop());}}
System.out.println(sb);
}
}
- 단어뒤집기 : Last In First Out : 스택 사용
- 괄호 안의 문자 / 괄호 밖의 문자(뒤집어야 함)의 구분 : in 변수 (flag)
- 전체를 한 번에 뒤집는 것이 아닌, 괄호를 기점으로 뒤집어야 하므로 괄호를 만나면 스택 전부 비움
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class P4949 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
boolean pEnd = true;
boolean result = true;
Stack<Character> stack = new Stack<>();
do {
String str = br.readLine();
if (str.equals(".")) { pEnd = false; break; }
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)=='.') { break; }
switch (str.charAt(i)) {
case '(' :
stack.push('(');
break;
case ')' :
if (!stack.isEmpty()) {
if (stack.peek() == '(') { stack.pop(); break; }
else { result = false; break; }
} else {
result = false;
break;
}
case '[' :
stack.push('[');
break;
case ']' :
if (!stack.isEmpty()) {
if (stack.peek() == '[') { stack.pop(); break;}
else { result = false; break; }
} else {
result = false;
break;
}
}
}
if (result && stack.isEmpty()) {
System.out.println("yes");
} else {
System.out.println("no");
}
result = true; stack.clear();
}
while (pEnd); {}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
boolean pEnd = true;
boolean result = true;
Stack<Character> stack = new Stack<>();
do {
String str = br.readLine();
if (str.equals(".")) { pEnd = false; }
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i)) {
case '.' :
break;
case '(' :
stack.push('(');
break;
case ')' :
if (!stack.isEmpty()) {
if (stack.peek() == '(') { stack.pop(); break; }
else { result = false; break; }
} else {
result = false;
break;
}
case '[' :
stack.push('[');
break;
case ']' :
if (!stack.isEmpty()) {
if (stack.peek() == '[') { stack.pop(); break;}
else { result = false; break; }
} else {
result = false;
break;
}
}
}
if (result == true && pEnd==true) {
System.out.println("yes");
} else if(result==false && pEnd==true) {
System.out.println("no");
}
result = true;
}
while (pEnd); {}
}
}
배운점 : 스택, 큐를 사용할 땐 반드시 루프마다 clear() 해주는 것을 잊지말자 ^-^
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<Character> stack = new Stack<>();
int result =0;
for(int i=0;i<n;i++) {
String str = br.readLine();
stack.push(str.charAt(0));
for(int j=1;j<str.length();j++) {
if(stack.isEmpty()) {
stack.push(str.charAt(j));
} else {
if(stack.peek()==str.charAt(j)) {
stack.pop();
} else {
stack.push(str.charAt(j));
}
}
}
if(stack.isEmpty()) {result++;}
stack.clear();
}
System.out.println(result);
}
}
직전에 나온 단어와 짝을 이루는지 확인하는 문제
: Last In First Out -> 스택을 활용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
Stack<String> stack = new Stack<>();
for(int i=0;i<n;i++) {
String str = br.readLine();
switch (str.charAt(0)) {
case '1' :
stack.push(str.substring(2));
break;
case '2' :
if(!stack.isEmpty()) {sb.append(stack.pop()+"\n");}
else {sb.append("-1"+'\n');}
break;
case '3' :
sb.append(stack.size()+"\n");
break;
case '4' :
if(stack.isEmpty()) {sb.append("1"+'\n');}
else {sb.append("0"+'\n');}
break;
case '5' :
if(!stack.isEmpty()) {sb.append(stack.peek()+'\n');}
else {sb.append("-1"+'\n');}
break;
}
}
System.out.println(sb);
}
}
그냥 주어진 연산을 수행하기만 하면 되는 정말 간단한 문제지만,
시간초과 문제를 마주쳤다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<String> stack = new Stack<>();
for(int i=0;i<n;i++) {
String str = br.readLine();
switch (str.charAt(0)) {
case '1' :
stack.push(str.substring(2));
break;
case '2' :
if(!stack.isEmpty()) {System.out.println(stack.pop());}
else {System.out.println(-1);}
break;
case '3' :
System.out.println(stack.size());
break;
case '4' :
if(stack.isEmpty()) {System.out.println(1);}
else {System.out.println(0);}
break;
case '5' :
if(!stack.isEmpty()) {System.out.println(stack.peek());}
else {System.out.println(-1);}
break;
}
}
}
}
- 알게된점
- System.out.println()으로 매 루프마다 데이터 출력을 진행하면 속도 현저히 느려진다
- StringBuilder : 내부 내용을 변경시킬 수 없는 String (불변)과 다르게
값을 변경해도 같은 주소공간을 참조하여, 값이 변경할 수 있는 가변성을 갖는다.
→ 매 번 출력하는 것보다 StringBuilder로 출력할 값들을 append하여 저장해두고, 마지막에 한 번에 출력하는 것이 시간을 줄일 수 있는 방법이다.
출력이 많은 문제에서는 매 번 System.out으로 출력하는 것을 지양할 것!!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<Character> stack = new Stack<>();
int cnt =0; int in=0;
String str = br.readLine();
for(int i=0;i<n;i++) {
if(str.charAt(i)-'0'>=1 && str.charAt(i)-'0'<=9) {
cnt++;
} else if(str.charAt(i)=='L') {
stack.push('L');
} else if(str.charAt(i)=='R') {
in = stack.search('L');
if(in!=-1) {
stack.remove(stack.size()-in);
cnt++;
} else {
break;
}
} else if(str.charAt(i)=='S') {
stack.push('S');
} else if(str.charAt(i)=='K') {
in = stack.search('S');
if(in!=-1) {
stack.remove(stack.size()-in);
cnt++;
} else {
break;
}
}
}
System.out.println(cnt);
}
}
stack - search() : 스택 내부에 해당 객체가 존재한다면, 위치를 반환한다 : 인덱스가 아닌 빠져나오는 순서, 즉 Last In이 0
stakc - remove() : 인덱스로 접근하여 삭제한다.
→ stack.remove(stack.size()-stack.search())를 사용하여 연계기술 사용시 선행기술이 존재하는지 찾고, 존재하면 해당 인덱스로 remove()를 수행했다LIFO도 필요했고 + 인덱스로 접근하는 부분도 필요해서 저 메소드를 사용하긴 했지만, 스택을 사용하면서 LIFO를 어기는 메소드를 쓰는게 맞는지는 모르겠다. 무엇보다 인덱스로 접근하므로 O(n)인 점을 생각하면 시간복잡도 상으로도 바람직하지 못 한 것 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Stack<Integer> stack = new Stack<>();
for(int i=n;i>=1;i--) {stack.push(i);}
Stack<Integer> dStack = new Stack<>();
Stack<Integer> cStack = new Stack<>();
while (true) {
StringTokenizer st = new StringTokenizer(br.readLine()," ");
if(Integer.parseInt(st.nextToken())==1) {
int d = Integer.parseInt(st.nextToken());
for(int j=0;j<d;j++) {
if(!stack.isEmpty()) {
dStack.push(stack.pop());
}
}
} else {
int d = Integer.parseInt(st.nextToken());
for(int j=0;j<d;j++) {
if(!dStack.isEmpty()) {
cStack.push(dStack.pop());
}
}
}
if(cStack.size()==n) {break;}
}
while(!cStack.isEmpty()) {
System.out.println(cStack.pop());
}
}
}