적으면서 문제풀기의 중요성

주민건·2020년 10월 11일
0

문제해결방법론

목록 보기
3/7

이전 시간이 말씀드렸던 문제해결절차가 기억나시나요?

물론, 안나실 것을 알기에 다시 한 번 적어봅니다.

  1. 문제분석: 목표, 상황 분석
  2. 방법생각: 무식한 방법부터 적용, 세부 목표 설정 및 관계 파악
  3. 제한검토: 시간복잡도, 공간복잡도, 문제 제한 상황에 맞게 동작하는 방법인지
  4. 코드구현: 모듈화
  5. 함수확인: 유닛 테스트

제가 절차는 소개해드렸지만, 왜 절차를 만든거고, 왜 적으면서 풀어야하는지는 덜 설명드린 것 같네요.
이 글에서 설명드리면서 설득이 아닌 강요(?)해볼까 합니다.

적으면서 풀면 뭐가 좋을까요?

문제에 대한 생각을 글로 적으면서 푼다는 것은 정말 귀찮은 일입니다.

귀찮은 일임에도 불구하고 해야되는 이유를 4가지 가져와봤습니다.

기억력이 대단하신가요?

만약 기억력이 엄청나게 좋으시다면, 적으면서 문제 풀 필요가 없습니다.

저는 기억력이 좋지못해서 갑자기 생각난 아이디어가 있다면 메모를 해야합니다.
마찬가지로, 문제를 풀 때에도 어떤 조건들이 있었는지 적으면서 이해하지 않으면
높은 확률로 예외케이스가 발생하거나 문제를 잘 못 풀 것입니다.

저는 생각의 흐름이 시냇물과 같다고 봅니다.
흐르는 시냇물에서 물을 움켜쥘 수 없듯이
생각하는 중에 특정 생각을 기억하고 있기란 쉽지않습니다.

시냇물과 비슷한 상황을 도로 위 차들에서 볼 수 있습니다.
버스 정류장에 앉아서 지나가는 차 안의 사람들 얼굴을 기억하는 것은 쉽지 않습니다.

기억의 종류에는 3가지가 존재합니다.

  • 감각기억
  • 단기기억
  • 장기기억

감각기억은 감각기관을 통해서 뇌에 저장되는 기억입니다. (I/O)
단기기억은 감각기억 중 주의집중한 기억이 저장됩니다. (Memory)
장기기억은 단기기억을 부호화를 통해 저장된 기억입니다. (Disk)

처음 문제를 만나서 문제 내용을 머리에 넣는데에 쓰이는 기억은
감각기억과 단기기억입니다.

감각기억은 여러 감각기관을 통해 들어온 기억이라 50ms~150ms만 유지되고, 빠르게 망각됩니다.
단기기억은 망각되지않게 주의집중한 감각기억이 저장되는데, 수초~1분 동안 저장됩니다.
기억할 수 있는 항목의 개수는 3~4개입니다. 숫자는 7개 정도입니다.

따라서, 기억의 특성상 많은 양의 정보를 오랫동안 한꺼번에 저장할 수 있지 못합니다.
문제가 복잡해서 깊이 생각하다보면 어느새 가장 처음에 왜 이 생각을 하게 됐는지 알 수 없습니다.

문제의 조건이 많고 까다롭고 생각을 깊게해야된다면 까먹기 쉽겠죠?

집중력이 대단하신가요?

적으면서 문제를 푼다는 것은
생각과 행동을 문제 푸는 데에 집중함으로
다른 생각들이 끼어들지 못하게 합니다.

생각의 흐름을 통제하지 못하거나, 특정 생각에서 더 깊이 가지 못한다면
내가 의도하지 않은 다른 생각으로 빠지기 쉽습니다.

앞의 둘, 모두 대단하시다면?

대단하시더라도 적으면서 푸는 것이 매우 도움이 됩니다.
기록의 장점에 대한 얘기를 안할수가 없네요.

문명의 단계를 구분하는데에 문자 사용이 빠질 수 없습니다.
문자로 인해 기록할 수 있게되고, 후대에 정보를 전해줄 수 있게된 것이죠.
현대의 예 중 컴퓨터 분야의 기술 블로그가 있습니다.

빠르게 본론부터 이야기하면, 생각을 적는 순간 분석이 가능해집니다.

문제를 풀면서 얻는 이점은
내가 어떤 생각의 흐름으로 현재 생각까지 도달했는지 알 수 있습니다.
어떤 이유에서 이 생각을 하게 되었는지 알 수 있게 되고,
해당 이유 및 논리를 뒤집어서 생각해보거나 방향을 바꿔 볼 수도 있습니다.

문제를 풀고나서 얻는 이점은
내가 문제를 풀 때 어떤 부분에서 실수를 많이 하는지 파악할 수 있습니다.
문제해결절차 중 어떤 단계에서 주로 막히는지 알아내어,
해당 부분을 개선시킬 수 있는 방법을 고민할 수 있습니다.
또한, 문제를 풀 때 어떤 생각 습관을 가지고 있는지 파악할 수 있습니다.
기록들을 비교하면서 습관을 개선시킬 수 있습니다.


(음.. 그렇군요..)

문제를 풀 때 생각 기록을 하면 가능해지는 전략

생각도 하나의 탐색 과정입니다.
탐색 과정을 기록한다면, 다시 되돌아 갈 수 있고, 다른 길로 갈 수 있습니다.

올바른 기록은 현재 상태를 파악할 수 있도록 돕습니다.
내가 무엇을 알고, 무엇을 챙겨야하는지 알게 해줍니다.

예를 통해서 여러 가능한 전략들을 살펴봅시다.

1. 가지고 있는 것을 펼쳐보자. 펼쳐진 요소들을 건드려보자.(증가, 감소, 제거 등)

내가 현재 처해진 상황을 분석합니다.
어떤 것을 가지고 있는지, 어떤 행위를 할 수 있을지 살펴봅니다.


목표: swap, 숫자 2개를 바꿔야한다.
상황:

  • 현재 숫자 2개는 2개의 변수에 담겨있다.
  • (대입연산자를 이용해야한다.)

방법:

  • 변수의 개수를 바꿔볼까?
  • 다른 연산자를 사용해볼까?

2. 컴퓨터가 아닌 내가 어떤 절차를 통해 목표를 달성하는지 관찰하자.

다른 사람에게 일을 전달하는 방법과 동일합니다.
여기서, 다른 사람이 컴퓨터라고 생각해봅시다.

명확하게 일을 전달하기 위해서는
일을 전달하고자하는 자신이 명확하게 어떤 절차로 일이 돌아가는지 이해하고 있어야합니다.


max

목표: 두 수 중 큰 수를 찾고 싶다.

Q.
컴퓨터가 아닌 내가 목표를 달성하기 위해 어떤 행위를 하는가, 절차를 밟는가?

A.
기준이 되는 수를 두고, 비교할 수를 둬서 기준 수가 비교하는 수에 비해 어떤 상태인지 본다.
컴퓨터에서는 조건문이 있다.


count, check

목표: 수열에서 특정 숫자 k가 몇 번 나왔는지 알고 싶다.

Q.
컴퓨터가 아닌 내가 목표를 달성하기 위해 어떤 행위를 하는가, 절차를 밟는가?

A.
숫자가 나올 때마다 체크를 하고, 체크한 개수를 세어준다.

Q.
체크를 컴퓨터로 할 수 있는가? 체크한 개수를 컴퓨터로 세어줄 수 있는가?

A.
있다면 코드로 변환, 없다면 조금 더 생각
체크할 수 있다 -> 조건문
체크한 개수를 컴퓨터로 세어준다는 것은 모르겠다.

Q.
내가 숫자를 어떻게 세었었는가

A.
어릴때는 손가락으로 세어줬다. 커서는 아무 종이에 숫자를 증가시켰다.
손과 종이에 해당하는 것이 변수구나.
변수에 숫자를 증감시킨다.
정리하자면 조건문으로 k인지 체크하고, 만약 k라면 변수에 숫자를 1씩 증가시켜준다.(단, 변수는 0부터 시작)


목표: 주어진 문장에서 알파벳이 각각 몇 번 나왔는지 알고 싶다.

Q. 내가 할 수 있는 것은 무엇일까?
-> 실습 한 번 해보시기 바랍니다.(키워드: 배열, 변수가 많다)

3. 문제를 작게 만들고, 생각을 점진적으로 넓혀보자.

한 번에 해결하기 어려운 문제는 내가 해결할 수 있는 단위로 쪼개서 분할 정복합니다.
할 수 있는 방법에서 목표 달성 할 때까지 확장합니다.


목표: 배열에서 가장 큰 수를 찾고 싶다.

Q.
내가 할 수 있는 것은 무엇일까?

A.
두 수를 비교해서 큰 값을 알 수 있다.

Q.
그렇다면 세 수 중 큰 값을 얻을 수 있는가?
그렇다면 네 수는?
그렇다면 배열을?

4. 생각의 방향을 바꿔보자

처음 떠올린 해결책의 논리 관계를 보고, 뒤집은 방향으로 적어봅니다.


실생활 예시

문제: 부탁한 물건을 이모가 들고와야하는데 매번 까먹는다.

Q.
꼭 이모가 들고와야하는가?

A.
내가 이모한테 가서 물건을 가져온다.


숫자 야구(https://www.acmicpc.net/problem/2503)

목표: 정답이 될 수 있는 후보의 개수를 알고 싶다.

처음에 드는 생각: 입력으로 주어진 숫자들을 통해 후보를 만든다.(규칙 -> 후보)

Q.
꼭 주어진 숫자들을 통해 후보를 만들어야하는가?
후보에서 주어진 숫자들을 걸러낼 수 없나?

A.
모든 후보에서 입력으로 주어진 숫자들을 통해 걸러낸다. (후보 -> 규칙)

5. ?

제가 설명해드린 전략 이외에 다른 여러 전략이 존재할 수 있습니다.

여러분이 문제를 적으면서 풀어보시고, 발견한 전략이 있다면 댓글로 남겨주시면 감사하겠습니다.
(예? 귀찮다고요? 알겠습니다..)

문제를 푼 후 기록 분석

문제를 푼 기록들이 쌓이면 해당 기록들을 통해 분석이 가능합니다.

데이터를 통해 습관 분석, 개선을 해보는거죠.

다시 한 번 문제해결절차를 가져와보겠습니다.
1. 문제분석: 목표, 상황 분석
2. 방법생각: 무식한 방법부터 적용, 세부 목표 설정 및 관계 파악
3. 제한검토: 시간복잡도, 공간복잡도, 문제 제한 상황에 맞게 동작하는 방법인지
4. 코드구현: 모듈화
5. 함수확인: 유닛 테스트

위 절차대로 문제를 해결하면서 내가 몇 번 절차가 잘 안되는지 파악할 수 있습니다.

만약 1번 절차가 잘 안된다면, 문제를 어떻게 읽어야 명확하게 이해할 수 있을지를 고민해볼 수 있겠죠.
떠올린 전략들을 직접 다음 문제를 풀 때 적용해보고, 실수 개선이 되는지 면밀히 관찰합니다.
만약 개선이 안된다면 다른 전략을 세워서 다시 실험해보는 과정을 반복합니다.

기록을 통해 알아낸 약한 부분을 강화하는 방향으로 계속해서 연습합니다.

적으면서 풀면 이게 좋군요?

라고 느껴주셨다면 매우 매우 감사합니다.

이로써 적으면서 문제풀기에 대한 강요의 글은 끝이 났습니다.

요약하자면, 적으면서 문제풀기의 좋은 점은 4가지 입니다.

  • 기억의 한계 극복
  • 집중력 강화
  • 생각 전략 수립
  • 생각 습관 분석

기록을 하자마자 마법같이 모든 문제가 해결되고,
앞서 설명한 절차대로 아름답게 문제없이 기록 할 수 있는 건 아닙니다.

메타 인지가 필요하고, 냉철한 분석력이 필요합니다.

자신의 생각을 군더더기 없이 작성할 수 있어야됩니다.

내가 3번에서 실수를 많이 한다고 생각했는데
근본적으로 1번에서 문제가 발생하여 3번에서 실수를 많이 할 수도 있습니다.

기록을 한다고해서 처음부터 잘 할 수는 없을 것입니다.
낙담하지 않고 기록하면서 문제 푸는 연습을 꾸준히 하는 것이 중요합니다.

막연히 문제를 푼다면 내가 어떤 문제점을 가지고 있는지 파악하기 어렵습니다.
기록을 통해 좀 더 쉽게 발견할 수 있으므로, 적극 권장드립니다.

다음 시간 예고

이번 글이 문제해결절차의 1번에 대한 간략한 내용이었다면,
다음 글은 문제해결절차의 2번에서 가장 중요한 "무식한 방법부터 적용"에 대한 내용을 다룰 예정입니다.
완전탐색은 어떻게 할까요? 완전탐색부터 어떻게 생각하죠?

profile
Learning Engineer

1개의 댓글

comment-user-thumbnail
2022년 8월 5일

좋은 글 감사합니다.
문제 해결을 설계 하는 방법에 대해 막막 했었는데, 덕분에 많은 도움이 된거 같습니다.
시간 있을때마다 와서 복습하고 가겠습니다 ㅎㅎ

답글 달기