본문 바로가기

유니티 스파르타 캠프 5주차

240507 백준 코딩테스트 문제

코딩 할 때, 내 실력은 어느정도일까? 궁금할 때 스스로를 돌아볼 수 있는 사이트인 백준입니다.

Baekjoon Online Judge

⚙ 어떤 점을 평가할 수 있는가?

코테를 하는 목적은 다양하겠지만, 그중에서도 저는 2가지를 꼽아볼 수 있다고 생각합니다.

첫번째로는 같은 구현이 가능한 코드 중에서도 어떤 코드가 가장 메모리나 속도면에서 효율적인지 고민해보고 다른 사람들로부터 배우기 위해서고

두번째로는 혼자서 다양한 문제를 직면하고 생각해보기에는 한계가 있으니, 많은 사람들이 제시하는 문제들을 풀어보기 위함이라고 생각합니다.

이는 오늘 제가 백준에서 풀었던 문제입니다.

List<int> stack = new List<int>();
int N = int.Parse(Console.ReadLine());
for(int i=0; i<N; i++)
{
	string[] str = Console.ReadLine().Split(" ");
	int a, b;

	if (str.Length == 1)
		a = int.Parse(str[0]);
	else
	{
		a = int.Parse(str[0]);
		b = int.Parse(str[1]);

		stack.Add(b);
	}

	switch (a)
	{
		case 2:
			if (stack.Count == 0)
				Console.WriteLine("-1");
			else
			{
				Console.WriteLine(stack[stack.Count-1]);
				stack.RemoveAt(stack.Count - 1);
			}
			continue;
		case 3:
				Console.WriteLine(stack.Count);
			continue;
		case 4:
			if (stack.Count == 0)
				Console.WriteLine("1");
			else
			{
				Console.WriteLine("0");
			}
			continue;
		case 5:
			if (stack.Count == 0)
				Console.WriteLine("-1");
			else
			{
				Console.WriteLine(stack[stack.Count-1]);
			}
			continue;
		default:
			continue;
	}

}

이 문제를 해결하기 위해서는 순차적으로 확인해보면 됩니다. 

코드 구조 : 명령의 수가 N개 -> 받을 값이 5가지 중 하나 -> 각 값마다 다른 출력
필요한 값 : 명령의 수(N), 명령(str), switch를 위한 값(a), 스택을 넣어줄 배열(stack) 

위에 제가 작성한 부분을 토대로 작성해보았습니다. 실제로 이렇게 적지는 않겠지만, 각 값을 하나씩 작성하며 이렇게 사용해야겠다는 마인드맵을 그리게 됩니다. 먼저, 위 코드는 시간제한이 걸려있었기에 시간 초과가 걸렸습니다. 

🔎 해결 방법? 

위에서 설명한 첫번째 이유대로, 이 코드는 구현이 가능할지언정 효율과는 먼 코드였습니다. 그렇다면 코드를 효율적이게 하는 방법을 탐색해보면 됩니다. 탐색해볼 부분은 이렇게 꼽았습니다.

continue? Console.WriteLine? int.Parse? Console.ReadLine?
공통점은 많이 쓴다는 것.

코테의 문제는 기본적으로 한 두번 쓰는 것으로 문제가 생길 것으로 생각되진 않았습니다. 그렇기에 많이 쓰이는 애들부터 대체방법이 있는지부터 확인하는 것을 시작으로 하였습니다. 

🎁 해결 과정

방향을 정했다면 하나씩 검색해보거나, 요즘 유행하는 ChatGPT와 같은 AI를 사용하시면 됩니다.(강추) 
AI를 활용할 경우에는 그 내용과 관련된 예제나 그에 대한 세부 설명을 해주기에 쓰기 좋습니다.
단, 무료버전은 횟수 제한이 있을 수 있으니 가능하면 먼저 검색을 하기를 바랍니다.

구글에서 검색하면 AI가 내용을 도와주기도 합니다. Console.ReadLine의 메모리 효율을 알기 위해 검색해보니, StringBuilder를 사용하면 메모리 효율성을 크게 향상시킬 수 있다고 합니다.합니다. 

👌 해결 완료

찾았다면 내용을 적용시켜보면 됩니다. 따라하기만 하면 실력이 늘까? 싶겠지만 문제를 많이 접하면 언제부턴가 혼자서도 습득이 되어 사용할 수 있습니다.

using System;
using System.Text;
//using System.Text;
//using static System.Net.Mime.MediaTypeNames;

namespace CodeRunning
{
	internal class Program
	{
		static void Main(string[] args)
		{
			List<int> stack = new List<int>();

			int N = int.Parse(Console.ReadLine());
			StringBuilder sb = new StringBuilder();
			for(int i=0; i<N; i++)
			{
				string[] str = Console.ReadLine().Split(" ");
				int a, b;

				if (str.Length == 1)
					a = int.Parse(str[0]);
				else
				{
					a = int.Parse(str[0]);
					b = int.Parse(str[1]);

					stack.Add(b);
				}

				switch (a)
				{
					case 2:
						if (stack.Count == 0)
							sb.AppendLine("-1"); //수정
						else
						{
							sb.AppendLine(stack[stack.Count-1].ToString()); //수정
							stack.RemoveAt(stack.Count - 1);
						}
						continue;
					case 3:
							sb.AppendLine(stack.Count.ToString());
						continue;
					case 4:
						if (stack.Count == 0)
							sb.AppendLine("1"); //수정
						else
						{
							sb.AppendLine("0"); //수정
						}
						continue;
					case 5:
						if (stack.Count == 0)
							sb.AppendLine("-1"); //수정
						else
						{
							sb.AppendLine(stack[stack.Count-1].ToString()); //수정
						}
						continue;
					default:
						continue;
				}

			}
			Console.WriteLine(sb.ToString()); //추가

		}
	}

}

StringBuilder를 사용하니 정답이 되었습니다. 이렇듯, 큰 구조를 바꾸지 않아도, 불필요하게 사용되는 메모리를 잡음으로써 쉽게 해결하는 방법을 알아갈 수 있었습니다. 

StringBuilder는 메모리를 크게 아낄 수 있는 반면, 사용하기는 매우 쉽습니다. Console.WriteLine이 사용될 부분을 AppendLine으로 StringBuilder에 저장했다가 한번에 출력하는 방법입니다. 매 입력마다 출력해야한다면 Console.WriteLine을 그대로 쓰면 되겠지만, Console.WriteLine을 불필요하게 여러번 호출한다면, StringBuilder를 써보시길 권장합니다!