내일배움캠프 - TIL/내일배움캠프 - TIL

내일배움캠프 15일차 - 백준 10828 팀 스크럼

rudals4469 2025. 4. 30. 22:43

오늘은 조원 분들과 팀 스크럼을 했다. 스크럼 내용은 대충 하루에 한 번 모여서 알고리즘 문제를 풀어보자! 였다.

그래서 정해진 오늘의 주제는 알고리즘 풀고 팀원들과 내용 토의하기!!

 

문제는 백준 10828 문제이다.

 

대충 알고리즘 - 스택 문제 중 만만해 보이는 문제로 선택되었다.

 

using System.Text;

namespace CodingExercise2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int inputNum = int.Parse(Console.ReadLine());                        // 명령의 수
            Stack<int> stack = new();

            for (int i = 0; i < inputNum; i++)                                   // 명령 수 만큼 반복
            {
                string[] input = Console.ReadLine().Split(' ');                  // 스플릿
                                                                                 // Push할 땐 push 1가 같이 들어오기 때문에
                                                                                 // push와 1을 나눠주기 위함
                                                                                 // input[0]에는 명령어가 input[1]에는 숫자가 들어올 꺼

                if (input[0] == "push")                                          // case 구문으로 할 까 했는데 귀찮아서 패스
                {
                    stack.Push(int.Parse(input[1]));
                }

                else if(input[0] == "pop")
                {
                    if(stack.Count == 0)    Console.WriteLine("-1");       
                    else                    Console.WriteLine(stack.Pop());
                }
                else if (input[0] == "size")
                {
                    Console.WriteLine(stack.Count);
                }
                else if(input[0] == "empty") 
                {
                    if(stack.Count == 0)    Console.Write("1");
                    else                    Console.WriteLine("0");
                }
                else if(input[0] == "top")
                {
                    if(stack.Count == 0)    Console.WriteLine("-1");
                    else                    Console.WriteLine(stack.Peek());    // top 출력을 어캐 할 까 하다가
                                                                                // https://learn.microsoft.com/en-us/dotnet/api/system.collections.stack?view=net-9.0
                                                                                // C# stack Document에서 Peek()이 top 반환 한다길래 바로 갖다 쓰기
                }

            }
        }
    }
}

 

처음에 내가 짯던 코드는 내장함수를 사용하여 이정도는 쉽네~ 하면서 팀원분들한태 보여줬다.

결과는 참혹하게 알고리즘 문제에는 내장함수를 안쓰는게 실력향상에 도움이 된다는 조언이었다.

생각해보면 당연한거였다. 스택을 공부하는데 스택 내장함수 한 줄로 띡 하는건 전혀 도움이 되지 않을 것 같았다.

 

그래서 스크럼 시간이 끝나가기전에 다시 리팩토링해서 다시 보여드리기로 했다. 

거기에 StringBuilder라는 사용법을 배워서 그거까지 사용해서 작성해보기로 했다.

 

그래서 작성한 코드는 다음과 같다.

 

using System.Text;

namespace CodingExercise2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int inputNum = int.Parse(Console.ReadLine());                        // 명령의 수
            
            List<string> list = new List<string>();

            StringBuilder sb = new StringBuilder();                              

            for (int i = 0; i < inputNum; i++)                                  
            {
                sb.Clear();
                string[] input = Console.ReadLine().Split(' ');         
                
                if (input[0] == "push")                                       
                {
                    list.Add(input[1]);
                }

                else if(input[0] == "pop")
                {
                    sb.Append(list.Count == 0 ? "-1" : list[list.Count - 1]);
                    // AppendLine으로 넣어주고
                    Console.WriteLine(sb.ToString());
                    if (list.Count != 0) list.RemoveAt(list.Count - 1);
                }
                else if (input[0] == "size")
                {
                    sb.Append(list.Count);
                    Console.WriteLine(sb);
                }
                else if(input[0] == "empty") 
                {
                    sb.Append(list.Count == 0 ? "1" : "0");
                    Console.WriteLine(sb);
                }
                else if(input[0] == "top")
                {
                    sb.Append(list.Count == 0 ? "-1": list[list.Count - 1]);
                    Console.WriteLine(sb);
                }

            }
            
            // 마지막에 ConsoleWrite(sb);
        }
    }
}

 

이번에는 리스트로 구현하여 각 명령어를 잘 구현했지만, 이번에는 StringBuilder의 사용법이 틀렸다!

위와 같이 사용하는 sb에 넣어주고 그걸 출력하기 때문에 오히려 성능에 더 안좋은 영향을 미친다고 한다.

차라리 sb.AppendLine으로 다 넣고 반복문을 나와서 Console.Write로 출력하는 것이 좋다고 한다.

처음에 나는 출력이 바로바로 나와야 되는줄 알고 이렇게 작성했는데 그러지 않아도 된다고 한다.

 

그래서 완성된 코드는

using System.Text;

namespace CodingExercise2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int inputNum = int.Parse(Console.ReadLine());                        // 명령의 수

            List<string> list = new List<string>();

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < inputNum; i++)
            {
                string[] input = Console.ReadLine().Split(' ');

                if (input[0] == "push")
                {
                    list.Add(input[1]);
                }

                else if (input[0] == "pop")
                {
                    sb.AppendLine(list.Count == 0 ? "-1" : list[list.Count - 1]);
                    // AppendLine으로 넣어주고
                    if (list.Count != 0) list.RemoveAt(list.Count - 1);
                }
                else if (input[0] == "size")
                {
                    sb.AppendLine(list.Count.ToString());
                }
                else if (input[0] == "empty")
                {
                    sb.AppendLine(list.Count == 0 ? "1" : "0");
                }
                else if (input[0] == "top")
                {
                    sb.AppendLine(list.Count == 0 ? "-1" : list[list.Count - 1]);
                }
            }

            Console.Write(sb);
        }
    }
}

 

위와 같다. 3트만에 팀원분들의 흡족한 ok가 떨어졌다.

그렇게 돌아가면서 코드리뷰는 끝나고

 

문제점이 하나 더 있었다. 조원분들 중 한 분이 "출력 시간 초과"가 나온 것이다.. 사실 코테를 풀다보면 쉽게 만나는 단어라곤 하지만 이런 문제에서 보기는 쉽지 않다고 한다. 우리는 머리를 맡대고 왜 이러지 고민을 해보다가

StringBuilder를 사용하지 않았다. RemoveAt과 같은 내장함수를 너무 많이 썻다. 라는 등의 의견이 나왔다.

 

우리끼리 머리를 싸매다 결국 정답은 도출되지 않았고.

 

튜터님께 물어보러 가게 되었다.

튜터님의 답변은 다음과 같다. 위의 케이스도 물론 성능에 영향을 미치지만 출력 시간 초과가 뜰 정도로 큰 효용을 보진 못한다.

아마 코드 자체가 제한 시간에 아슬아슬 하게 걸쳐 있는 상태에 누구는 StringBuilder를 사용하여 안쪽으로 들어왔고 쓰지 않은 사람은 밖으로 나간 것 같다. 라고 하셨다.

 

실제로 내가 StringBuilder를 사용하지 않는 코드는 400이 떳고 제한은 500이였다. 즉 100만 더 느린 코드가 짜졌어도 통과를 못하는 것이다. 애매하긴 하지만 확실히 StringBuilder를 사용했을 땐 60대로 떨어지는 걸 보니 알고리즘 문제를 풀 땐 쓰는 것이 좋아 보이긴한다.