알고리즘

99클럽 코테 스터디 4일차 TIL 올바른 괄호 feat(queue.add vs offer)

ernest45 2024. 5. 23. 20:38

https://school.programmers.co.kr/learn/courses/30/lessons/12909/

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

queue.add vs offer

 

1.  접근 방식

 

 

문제는

 

올바른 괄호를 만드는 건데 (로 시작했음 )로 닫혀야 한다.

true or false로 반환 100,000

 

 

내 생각엔

 

1. 시작은 무조건 (

2.끝은 )

3.짝수

 

 

다 통과했다면

큐에 ( 넣고,  ) 빼서 queue 비었는 반환하면 같다..

 

 

 

 

2. 문제 풀이

 

 

private boolean solution(String s) {

    Queue<Character> queue = new LinkedList<>();
  

    if (s.length() % 2 != 0 || s.charAt(0) != '(' || s.charAt(s.length() - 1) != ')') {
        return false; // 기본 조건 짝수가 아니거나 (로 시작하지 않거나, )로 끝나지 않거나 바로 false
    }

    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == '(') { // (,) 둘 중 하나만 들어옴
            queue.offer(s.charAt(i));  //add, 와 offer , remove 과 poll는 실패시 false냐 오류냐 
            // add,remove는 실패시 예외,  offer,poll은 false 반환

        } else // 시작부터 닫는 괄호면 ? poll 했을 때 뺄 수 있는 게 없기에 false 반환이지만, (틀림)
            if(queue.isEmpty())
                    return false;
                    // ++ 이렇게 안했는데, 예외 테스트하다 빈 곳 찾음(그래도 통과하더라.. 허술해)

                else
                    queue.poll();
                // 시작을 미리 걸렀기에 )부터 실행될 일은 없다.
    }


    return queue.isEmpty();
}

 

 

 

2-1 기본 조건

if (s.length() % 2 != 0 || s.charAt(0) != '(' || s.charAt(s.length() - 1) != ')') {
    return false; // 기본 조건 짝수가 아니거나 (로 시작하지 않거나, )로 끝나지 않거나 바로 false
}

 

 

먼저 기본 조건으로 홀수거나  '(' 로 시작하지 않거나   or      ')'  닫히지 않는다면 바로 false return 하게 해줘서 걸러줬다.

 

 

 

2-2 for문

 

for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) == '(') { // (,) 둘 중 하나만 들어옴
        queue.offer(s.charAt(i));  //add, 와 offer , remove 과 poll는 실패시 false냐 오류냐 (offer,poll을 쓰자 안정성)

    } else // 시작부터 닫는 괄호면 ? poll 했을 때 뺼 수 있는 게 없기에 에러가 날껀데
        if(queue.isEmpty())
                    return false;
                    // ++ 이렇게 안했는데, 예외 테스트하다 빈 곳 찾음(그래도 통과하더라.. 허술해)

                else
                    queue.poll();
                // 시작을 미리 걸렀기에 )부터 실행될 일은 없다.
}

 

 

시작의 경우 (라면 queue에 넣어줘서 queue의 크기를 하나 늘려줬고,

아닌 경우라면 빼줘서 사이즈를 줄여줬다.

 

( 가 없는데   )가 계속 온다면 poll이니 false가 바로 리턴될 것이다.!

 

 

 

놀랍게도 틀린 부분이 있어 수정한다 나는 queue.poll(); 이 실행되고 만약 뺄 게 없다면 바로 false를 리턴할 거라고 생각했지만

그렇게 작동하지 않았다.. 그래서 비었을 경우 poll을 하면 바로 false 리턴하게 만들었다.

 

 

예측하기로는 object를 받고 있으니 상황에 맞게 리턴될 거 같은데 poll시 명시적인 boolean(못 뺄 경우) 값 or int(poll한 값)

으로 나와서 그런 거 같다.. 메서드 타입 자체가 boolean 값이니까 이거 수정하면 될 거 같기도..

instanceOf를 쓰면 되려나 ?

 

++ 수정(2024 5/24)

더 찾아보니까 poll은 다르게 false가 아니라, null을 반환한다. 그래서 틀린 듯

 

 

우리의 최종 목표는 올바른 괄호라면 queue를 비게 만드는 것이다.

 

 

 

 

 

 

 

 

! 여기서 

 

queue에 넣는 메서드인 add와 offer의 차이는 

실패 시에 offer는 false를 반환하는 반면, add는 예외를 던진다.


(내 생각엔 예외를 발생하게 해 처리를 따로 해주는 게 더 안정적으로 보이는데..결과 값과 다르게 그냥 false를 반환하게 하는 게 맞나 ?)

 

 

remove와 poll의 경우도

마찬가지로 실패 시 poll은 false 처리, remove는 예외를 던진다. !

 

++ 수정 (2024 0524)

poll은 queue가 다 차있을 경우 false가 아니라 null을 반환함

 

 

 

 

 

조건에서 (,) 밖에 없다고 가정하였기에 else로 처리했고

 

애초 시작 조건에서 )로 시작하는 경우를 먼저 처리했기에 remove의 경우 예외가 발생하지 않음 !

 

 

 

 

마지막으로 

 

queue가 비었는 지 안 비었는 지를 return 해주면 원하는 true , false로 정답이 나온다..

 

 

성공 !

 

 

 

 

3. 느낀 점 && 궁금함

 

 

queue의 활용법과 다시 한번 더 만들어 봐야하는데..

 

add와 offer의 동작원리도 자세하게 몰랐는데,, 알아가서 좋다 

 

근데 여기서 궁금한 게 offer시 capacity가 다 찼다고 가정하면 false를 반환하게 될텐데.. 

차라리 add로 발생할 수 있는 예외를 다 잡는 게 더 안정적이지 않을까 ?

 

 

 

즉 offer를 사용하면  오류 시 아예 다른 결과 값이 나오는 거고,

add를 사용하면 아예 에러가 나니까

 

 

 

예외를 완벽하게 예측 못할 경우 프로그램을 죽이는 것 보다 차라리 다른 결과 값이 안정적인건가..

의문이다

 

 

 

 

 

찌삐띠 형님은 이렇다구 하시네..

 

 

다른 사람의 풀이를 보면서 더 좋은 방식이 있음 추가하겠다 !

 

 

 

++ 다른 사람 풀이 추가!!

 

https://velog.io/@slz6k/99%ED%81%B4%EB%9F%BD-%EC%BD%94%ED%85%8C-%EC%8A%A4%ED%84%B0%EB%94%94-4%EC%9D%BC%EC%B0%A8-TIL-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%AC%EB%B0%94%EB%A5%B8-%EA%B4%84%ED%98%B8 같은 반 분의 풀이

 

 

 

 

stack을 활용법

 

닫힌 괄호를 만났는데 비어있다면(열린 괄호가 없다면)

poll이라 false가 바로 return 될 줄 알았는데 그렇게 작동안했다..

 

바로 return을 해주니까 좀 명시적이라 좋을 것 같다 !

 

수정 후 결국 내 코드에서 queue나 stack 둘 중 하나를 알아서 쓰면 될 듯

 

 

 

 

 

 

 

Q) 보편적인 안정성이란 프로그램을 죽이지 않는 것이냐? 값의 안정성이냐 ?

 

 

 

A) 

프로그램마다 다르다

금융데이터 및 병원의 경우 프로그램을 멈추더라도 오차를 줄여야 하고, 돌아 가는 게 더 중요한 메세지 및 피드 서비스라면

값이 살짝 달라져도 프로그램을 죽이지 않는 것이 유리 할 수 있다..!

 

 

 

코테의 문제라면 ?

 

애매하다.. 답이 제일 중요할 것 같은데 프로그램을 멈추는 거 보다 답이 살짝 틀려도 될려나..

그래도 이럴 경우 프로그램이 먼저인 것 같다 ! 진짜 웬만한 중요한 데이터들(금융,의료)이 아닌 이상 버그가 발생 하는 게 아주 조금 더 나을 수도 있겠다는 생각이 든다..

 

근데 코테는 쭉 돌아 가는 게 아니잖아~ 그럼 걍 답의 안정성으로 써야겠다..

 

 

그리고 상황마다 잘 파악해서 어떤 걸 return 할 지는 내가 결정하는 것이니

 

상황 별 파악이 제일 중요하다 ! 모든 에러를 예측할 수 없으니 변수 고려 필수 !!

 

 

 

 

 

 

혼자 공부하는 것 보다 소정의 비용을 내고 참가했는데

 

다른 분들의 답변과 무엇보다 클럽장이나 운영진 분들의 빠른 대답과 예시들이 큰 도움이 되는 것 같다.

같이 하는 것이 역시 더 도움이 된다..!