문제 해결 접근법 - 알고리즘3

Junho Yun·2022년 11월 10일
0

알고리즘

목록 보기
3/18
post-thumbnail

문제 해결법 소개

알고리즘 문제를 풀기 위해서는 기본적으로 문제를 이해하고 정의하고 어떻게 해결할 지 정해야합니다. 그에 대한 내용을 담았습니다.

알고리즘이란 무엇일가요?
어떤 작업을 해결하기 위한 방식입니다. 유튜브 알고리즘의 선택을 받았다는 말을 들어 보셨나요. 거기서 말하는 유튜브 알고리즘은 유튜브에서 사용자에게 최적화된 혹은 더 시청할 법한 영상들을 추천해주는 추천 알고리즘입니다. 이 알고리즘을 통해 끊임없이 볼만한 영상을 추천해주는 것이죠.

어떻게해야 알고리즘을 잘 이해할까요?
누군가는 쉽게 이해하고 적응하지만 어려움을 겪는 사람들도 있을 것 입니다.

  • 문제해결을 위한 계획을 수립하는 것 입니다.
  • 일반적인 문제 해결 패턴을 파악하는 것 입니다.

문제의 이해

개발자가 하는 일은 문제(배달시키는게 불편해)를 코드(배민)으로 해결하는 역할 입니다. 문제를 잘 해결 하기 위해서 첫번째로 문제를 잘 이해하는 것이 중요합니다.

프로그래밍을 하다보면 아직 머릿 속에 문제가 정리되지도 않았는데 코드를 짜는 나의 모습을 볼 수 있습니다. 단순한 문제에서는 이렇게 동작할 수 도 있지만 복잡한문제일 수록 이러한 방식은 좋지 않습니다.

문제를 이해했는 지 확인하는 법

  • 나만의 단어로 혹은 문장으로 다시 표현할 수 있는가?
  • 문제에 들어가는 인풋(INPUT)이 무엇인가? 어떤 형태인가?
  • 아웃풋은 어떤 무엇일까요? 해결책에서 어떤 결과가 도출되어야 하는가?
  • 그래서 내가 만든 함수에서 반환해야 하는 결과는 어떤 것인가
  • 내가 알고있는 입력값을 통해 출력값을 결정할 수 있을까? (코드를 짜기 전까지는 확답을 못할 수도 있지만 고민을 해보는 것이 좋은 습관)
    *추가설명 : 문제를 잘 못이해했다면 필요한 인풋은 3개인데 2개만으로 출력값을 만들려고 할수도 있겠죠
  • 문제의 핵심이 무엇인가?

위의 내용을 기반으로 예제를 풀어보겠습니다.
ex. 두개의 숫자를 받아서 그들의 합을 구하는 함수

  1. 두개의 숫자를 덧셈하라 (문제가 짧아서 비슷하네요)
  2. 입력 값은 : 두 개의 숫자 인데...얼마나 큰값인지 소수인지 정수인지 등등 세부적으로 생각하기. 매우 큰 값을 연산이 안될 수도 있습니다.
  3. 출력 값은 : 한개의 숫자입니다. 이는 문자열도 될 수 있고 소수 일수도 있고 등등 여러 방식이 있겠죠.
  4. 만약의 하나의 숫자만 준다면 어떻게 작동해야할까...? 일단은 무시하고 2개의 숫자로만 구성해보자
  5. num1, num2 를 받아서 sum을 반환하도록 add라는 함수를 만들어줍니다.

구체적 예제들

예시를 떠올리는 것은 문제를 잘 이해하는 것에 도움이 됩니다.

  • 문제를 만나면 간단한 예시로 시작해보는 것 입니다.
  • 조금 더 복잡한 예시로 진행하기
  • 예시를 입력값이 없을 때를 고려해봅니다.
  • 입력값이 유효하지 않을 때를 고려해봅니다.

ex. 문자열을 받아서 각 문자의 수를 반환하는 함수를 작성하라.

  • charCount 라는 함수를 떠올려봅니다. (aaaa 입력 -> a:4 출력)
  • "my phone number is 030-4994-4949" 이라는 인풋일 때, 아웃풋을 어떻게 할 것 인가? 숫자를 포함할 것인지 -와 공백은 어찌 처리할 것인가 ?
  • charCount("")을 했을 때는 어떤 아웃풋을 해야할까?
  • 올바르지 않은 값을 인력 했을 때는 어떤 아웃풋을 해야할까?

세부 분석

면접에서 알고리즘테스트를 본다면, 이는 면접관이 당신과 소통하고 싶다는 것 입니다. 짜증내면서 문제를 바로 푼다면 좋게 보이지 않을 것 입니다.

  • 해결책의 기본요소를 단계별로 정리해봅시다. 코드가 아니더라도 글 혹은 기호를 이용할 수도 있겠죠.
  • 이를 통해 어떤 부분이 부족한 지 이해못했는지 확인할 수 있습니다.

아까와 같은 문제를 예시로 확인해보겠습니다.

function charCount(str){
	// do something
    // return 키들을 가진 객체 형식의 값을 반환합니다. 
}

function charCount(str){
	// 객체 선업 (반환할 때 사용)
    // 배열을 반복문을 사용해서 알파벳 확인 , for each character
    	//if (숫자/문자이며 char가 키값으로 존재하면), count +1 해주고
        //if (숫자/문자이며 char가 키값으로 존재하지 않으면), 객체에 해당 키를 추가해주고 값을 1로 설정
        //if (숫자/문자 가 아닐 경우) 아무것도 하지 않는다 
    // 객체를 반환 합니다.
}

이렇게 의사코드를 작성한 뒤에 이를 바탕으로 코드를 만들어줍니다. 면접을 진행시에도 코드를 못 짤 경우 이렇게라도 문제를 이해했다는 것을 표현해야 할 수도 있습니다. (일부러 매우 어려운 문제를 주고 과정을 확인하는 경우도 있기 때문입니다)

해결 또는 단순화

만약 문제를 풀 수 없다면 단순화 해서 적용해봅시다.

  • 문제 중에 가장 어려운 부분을 찾습니다.
  • 일시적으로 그 부분을 무시합니다.
  • 단순화된 해결책을 작성합니다.
  • 가능하다면 어려운 부분을 다시 통합해서 해결합니다.

ex 위의 문제에서 대소문자 처리하는 것이 어렵다면 해당 부분은 무시하고 작성합니다. 그리고 추후에 해당 부분을 풀 방법을 다시 해결하는 것 입니다.

function charCount(str){
	let result = {};
	// 객체 선업 (반환할 때 사용)
    for (let i = 0; i< str.length; i++){
    // 배열을 반복문을 사용해서 알파벳 확인 , for each character
    	if(result[char]>0){
        	result[char]++;
        } else {
        	result[char] = 1;
        };
        //if (숫자/문자이며 char가 키값으로 존재하면), count +1 해주고
        //if (숫자/문자이며 char가 키값으로 존재하지 않으면), 객체에 해당 키를 추가해주고 값을 1로 설정
        //if (숫자/문자 가 아닐 경우) 아무것도 하지 않는다 
        }
        return result;
    // 객체를 반환 합니다.
}

여러 예외를 해결하지 못했지만 부분적으로는 문제를 해결했다고 볼 수 있습니다. 정규표현식 혹은 아스키 코드등을 활용해서 유효한 문자인지 아닌지를 확인할 수 있습니다.

되돌아보기와 리팩터

위의 과정을 통해 얻은 해결책이 좋든 형편없든 되돌아보고 미비한 부분을 다시 정리해야 합니다.

코드를 한 줄씩 살펴보며 마음에 들지 않는 부분들을 수정하는 것입니다.
코드의 효율성 및 가독성을 살펴보는 것 입니다.

  • 올바른 결과 값이 나오는 지
  • 결과를 다른식으로도 도출 가능한가?
  • 한 눈에 알아보기 좋은가요 (가독성)
  • 더 좋은 해결 방법은 없을까?
  • 이 해결 방법으로 다른 문제에도 적용이 가능한가?
  • 다른 요소들은 괜찮은 지(ex 변수명 지정이 올바른가. 코드 공백이 자연스러운가 등등)
  • 다른 사람들이 이 문제를 어떻게 해결했는가.

다른 사람들이 문제를 어떻게 해결했는 지를 통해서 많은 것을 배울 수 있지만 항상 다른 사람의 해결책만 보고 따라한다면 새로운 문제에 접근하는 방법 및 능력을 키우지 못할 수 있습니다.

리팩터의 예시로는 for 대신 for of 를 사용하고 if else문의 가독성을 좋게 만들어주기 위해서 삼항다항식을 쓰는 것 등을 예로 들 수 있다.

복습과 인터뷰 전략

  1. 문제를 이해하라
  2. 구체적인 예시를 살펴봐라
  3. 문제 해결을 위한 단계를 몇가지 단계로 세분화해라
  4. 단순화해서 해결 후 통합해라
  5. 코드를 되돌아보고 리팩토링해라. (공부 및 연습에서는 가장 중요)
profile
의미 없는 코드는 없다.

0개의 댓글