1. 문제
입력된 n 값에 해당하는 숫자들이 주어지는데, 오름차순으로 스택에 넣되 케이스에 맞는 결과를 + , - 에 맞게 출력해야 한다.
2. 제출 결과
3. 문제 발생 > 두 객체 간의 비교
while (data.size() != 0) {
if (stack.isEmpty() && idx == 0) { // 초기상태
stack.push(num);
sb.append("+").append("\n");
num++;
} else if (stack.peek() > data.get(idx)) { // 수열 불가능한 경우
sb.delete(0, sb.length());
sb.append("NO");
break;
}
if (stack.peek() == data.get(idx)) {
stack.pop();
data.remove(idx);
sb.append("-").append("\n");
} else if (stack.peek() != data.get(idx)) {
stack.push(num);
sb.append("+").append("\n");
num++;
}
}
반례들을 다 입력해봐도, 정답에 맞게 잘 출력되었는데 백준에서 아무리 제출해도 틀렸다고 나왔다.
곰곰이 생각해 본 결과, Stack 과 ArrayList 객체를 생성할 때 Integer 타입으로 만들었는데
기존 코드 조건문에서 == 연산을 수행할 경우, 참조타입의 객체인 경우 객체의 주소를 비교해 일치하는지 확인하게 된다.
하지만, 내가 생각했던 건 stack.peek() 값과 리스트인 data 에서 get 한 값을 비교할 경우 int 타입의 정수가 나올 줄 알았지만,
자바 도큐먼트를 참고한 결과, peek() 메소드의 반환 타입은 스택을 생성할 때 타입을 지정한 타입으로 반환하게 된다.
int x = stack.peek() OR int y = data.get(idx) 를 따로 생성하고, x == y 를 하지 않는 이상은
Integer 타입의 객체끼리 주소를 비교하게 된다.
int x = stack.peek(); 인 경우에는, stack.peek() 를 리턴한 Integer 타입이 자동으로 언박싱되기 때문에
int 타입으로 값 비교 == 연산이 가능하게 되는 것이다.
따로 정수형으로 만들어서 비교하는 게 아니라 객체 타입으로 비교할 경우에는
객체의 내용을 비교하는 .euqlas() 를 이용하는 것이 가장 안전하고 좋은 방법이다!
= =
타입이 byte, short, int 인 경우에는 -128 ~ 127 범위에 해당할 때, == 와 != 연산자로 비교할 수 있지만
해당 범위를 벗어나는 경우에는 내부 값을 비교하는 것이 아니라 객체 번지를 비교하게 된다.
해당 문제 같은 경우에는 n(1 <= n <= 100,000) 범위가 주어졌기 때문에
당연히 == 연산을 수행한 경우, 범위에 벗어나 객체 번지를 비교하게 되기 때문에 문제에서 틀리게 된 것이다.
따라서, equals() 를 사용하고 제출한 경우 통과를 하게 되었던 것이다.
4. 해결 방법 > .equals() 사용
while (data.size() != 0) {
if (stack.isEmpty() && idx == 0) { // 초기상태
stack.push(num);
sb.append("+").append("\n");
num++;
} else if (stack.peek() > data.get(idx)) { // 수열 불가능한 경우
sb.delete(0, sb.length());
sb.append("NO");
break;
}
if (stack.peek().equals(data.get(idx))) {
stack.pop();
data.remove(idx);
sb.append("-").append("\n");
} else {
stack.push(num);
sb.append("+").append("\n");
num++;
}
}