소개
문과생도 이해하는 알고리즘 강의를 가르치는 강사 개발자로 취직하기입니다 :)
저는 문과생 출신으로 현재는 8년차 대기업 개발자입니다. 처음 코딩을 접하고 코딩 테스트 준비를 하던 막막한 시절을 떠올리며, 어떻게 하면 조금 더 쉽게 설명할 수 있을지, 저 같은 비전공자 문과생도 이해하고 새로운 기술을 습득할 수 있을지 고민하며 강의를 제작하고 있습니다.
유튜브 통해서도 무료 강의 진행하고 있으니 많은 관심 부탁 드립니다!
https://www.youtube.com/@gaebal
강의
수강평
- [파이썬/Python] 문과생도 이해하는 DFS 알고리즘! - 입문편
- [자바/Java] 문과생도 이해하는 DFS 알고리즘! - 입문편
- [자바/Java] 문과생도 이해하는 DFS 알고리즘! - 입문편
- [자바/Java] 문과생도 이해하는 DFS 알고리즘! - 입문편
- [자바/Java] 문과생도 이해하는 DFS 알고리즘! - 입문편
게시글
질문&답변
재귀함수 질문
안녕하세요 🙂 우선 두 함수를 더 정확하게 예제로 작성해주시면 질문을 이해하기 더 쉬울 것 같아요. 여기서 베이스 케이스가 정확히 어떤 의미인지 확실하지 않아서 답변 드리기 고민되는데, 현재 이해한 대로 답변 드리고 부족한 부분 있으면 추가 질문 부탁드려요!두 코드의 동작은 동일합니다. Python에서는 명시적으로 return을 작성하지 않아도 함수가 끝나면 암묵적으로 None을 반환하고 종료됩니다. 따라서 두 코드 모두 실행 결과는 동일하며, 동작에 차이는 없습니다. 그러나 코드 작성 의도와 가독성 면에서 약간의 차이가 있습니다.첫 번째 코드에서는 return을 명시하지 않아 함수가 자연스럽게 종료되도록 작성한 것으로, 특별히 함수 종료를 강조하지 않습니다. 이 경우, 단순히 함수의 끝에서 아무 작업도 하지 않고 넘어가는 상황이라면 적합합니다.두 번째 코드에서는 return을 명시적으로 작성하여 함수가 해당 위치에서 종료된다는 것을 분명히 나타냅니다. 이는 베이스 케이스를 명확히 구분하고자 하거나, 함수 종료를 코드 상에서 의도적으로 강조하고 싶을 때 사용합니다. 특히 협업 상황에서 코드의 의도를 명확히 전달하기 위해 유용할 수 있습니다.결론적으로 두 코드의 실행은 같지만, 첫 번째 코드는 단순하고 암시적인 종료를 의도한 경우에 적합하고, 두 번째 코드는 의도를 명확히 표현하고 싶을 때 더 적합합니다. 상황에 따라 적절한 방식을 선택하면 됩니다.
- 1
- 1
- 33
질문&답변
안녕하세요, 혹시 다른문제도 여쭤볼 수 있을까요?
안녕하세요 김예현님!강의가 도움 되셨다니 다행입니다. 원래는 다른 문제 답변은 못 드리는데, 이번 문제는 저도 이미 풀었던 문제라 간단하게 답변 드리겠습니다 🙂 작성하신 코드에 따르면 DFS 순서와 입력 순서가 정확히 일치하는 경우에는 정답이 나오지만, 둘이 일치하지 않을 경우에는 오답이 나올 수 있을 것 같아요. 트리 구조는 고려하지 않는 단순 비교 방식이라 둘이 같아야만 1을 출력하여 오답이 되지 않을까 싶습니다.제 생각에 더 나은 답안은 DFS를 사용해서 트리 구조를 분석하고, 서브트리 크기와 깊이를 고려해야 입력 순서가 달라지더라도 트리 구조상 유효한지 아닌지를 판단하고 1 혹은 0을 제대로 출력할 수 있을 것 같습니다!제 답안 참고로 보내드리니 DFS 순서와 입력 순서가 다른 경우를 두 코드로 돌려보시면서 차이를 보셔도 이해에 도움 될 것 같습니다. 공부 화이팅하세요!import java.util.*; public class Main { static int N; static ArrayList[] graph; static boolean[] visited; static int[] level, tsize; static int[] order; public static int dfs(int node, int lv) { if (visited[node]) return 0; visited[node] = true; level[node] = lv; int size = 1; for (int next : graph[node]) { size += dfs(next, lv + 1); } tsize[node] = size; return size; } public static void main(String[] args) { Scanner input = new Scanner(System.in); N = input.nextInt(); graph = new ArrayList[N + 1]; visited = new boolean[N + 1]; level = new int[N + 1]; tsize = new int[N + 1]; order = new int[N]; for (int i = 1; i (); } for (int i = 0; i = N) continue; int next = order[i + tsize[node]]; if (level[next] > level[node]) { System.out.println(0); return; } } System.out.println(1); } }
- 1
- 1
- 23
질문&답변
촌수계산(백준 2644) 질문
AI AI 님 안녕하세요 🙂이 경우에는 가장 작은 노드부터 시작하지 않아도 동일한 답이 나올 수 있을 것 같아요!다만 작은 노드부터 큰 노드까지 방문하는 게 직관적이기도 하고 코드 구현도 단순해서 이렇게 많이 구현하는 것 같습니다 🙂 현재는 두 노드 간의 거리를 계산하는 문제와 같으니 동작에 차이는 없을 것 같습니다!
- 1
- 2
- 40
질문&답변
다른 주제 강의
안녕하세요 AI AI님! 죄송스럽게도 아직 구체적인 일정이 나온게 없습니다 ㅠ 조금씩 추가 준비는 하고 있지만, 계획에 없던 대학원 생활을 하게 되고, 생각보다 널널하지 않다는 걸 와보고서야 알게 되었네요 ㅠ. 그래도 아예 포기한 것은 아니고 최대한 틈 내서 준비하고 있습니다..!! 얼른 더 좋은 강의로 돌아오겠습니다!
- 1
- 2
- 39
질문&답변
최근에 올린 질문, 코드블럭으로 공유드립니다!
예현님 안녕하세요! 제 생각에는 출력해야 되는 내용을 잘못 이해하셔서 문제가 발생하는 것 같은데, 공교롭게도 예시에서는 그 차이가 뚜렷하게 보이지 않아서 헷갈리는 것 같습니다.우선 문제에서 요구하는 건 '각 숫자가 출력된 순서' 이기 때문에, 우리가 배열에 담아야 하는 값은 '순서'이고, 담아야 할 배열의 위치(index)가 숫자가 되는 겁니다. 그래서 결과적으로 answer[2] = 4라고 한다면 2번 노드는 4번째 방문됐다 라는 것이 문제에서 요구한 것이고, 그래서 정답이 위에 말씀해주신 제 코드처럼 나오게 됩니다!예현님께서 작성하신 코드는 반대로 '각 순서에 출력된 숫자'를 구현하셨기 때문에 배열에 담기는 값이 '숫자(idx)'이고, 위치가 순서가 됩니다. 한 가지 예시를 들자면, dfs 동작 상 노드 방문 순서가 다음 같다고 가정할게요: 1 -> 5 -> 2 -> 3 -> 4. 그러면 예현님 답은 이 순서 그대로 출력을 하겠지만, 문제에서 원하는 답은 1 3 4 5 2 가 될겁니다.왜냐하면 1은 첫번째 방문했고, 2는 3번째 방분, 3은 4번째 방문, 이런 식이기 때문입니다! 결론은 코드는 문제가 없어보여서 잘 나오는데, 다만 문제에서 의도한 정답을 잘못 이해하셔서 그런 것 같습니다! 문제 다시 한번 확인해보시고 혹시 추가로 궁금한 점 있으면 말씀해주세요!!
- 1
- 1
- 32
질문&답변
질문이 있습니다. dfs 메서드에 order를 이렇게 구현하면 안되는 이유가 무엇인가요?
안녕하세요 예현님 🙂 코드를 스크린샷 말고 코드 블럭으로 공유 부탁드립니다!공유해주시는 대로 확인해보겠습니다~
- 0
- 2
- 45
질문&답변
Max로 초기화하는 이유
안녕하세요 color.park님 🙂 우선 결론부터 말씀 드리자면 n+1, m+1로 하셔도 됩니다! 이렇게 작성하는 게 더 최적화된 답변일 수 있어서 손에 익으신 다음에는 이렇게 작성하는 것이 더 좋을 것 같습니다.다만 제가 MAX로 초기화 하는 이유는 1) 코드를 단순하게 작성해서 공부하실 때 수월하시기 위해서와 2) 혹시라도 예상하지 못한 불량을 방지하기 위해서입니다! n+1, m+1로 당연히 될 줄 알지만 꼭 하나씩 더 필요하거나, 예상과 달라지는 경우들이 생기고, 시험장에서 이런 경우가 발생하면 멘탈 관리가 어려워서 떨어지시는 분들이 많더라고요. 나중에 알고보니 그냥 max로 초기화했으면 아무런 문제가 되지 없어서 한번 더 멘탈이 나가곤 하셔서, 메모리를 살짝 낭비하는 대신 문제를 안전하고 빠르게 맞추는 것이 나을 것 같아 이렇게 추천드립니다! 그렇지만 굳이 필요없다고 판단되시면 최적화 하셔도 됩니다 :)
- 1
- 2
- 80
질문&답변
백준 24479 문제 제출 결과 "틀렸습니다" 라고만 나와서 어떤 부분이 틀렸는지 잘 모르겠어요 피드백 부탁드립니다
AI 인턴보다 한 발 늦었지만 두 가지 수정하면 될 것 같습니다! 엣지 읽기 루프:엣지를 읽는 루프가 1부터 N + 1까지 반복되는데, M개의 엣지를 읽어야 합니다. 현재 구현은 N이 M보다 크면 필요한 것보다 더 많은 엣지를 읽을 수 있습니다!방문 순서 초기화:방문 순서(visitOrder)가 시작 노드 R로 초기화됩니다. 방문 순서는 1부터 시작하되, 첫 노드 번호를 R로 초기화 하도록 수정하면 정답이 될 것 같습니다 🙂
- 1
- 3
- 104
질문&답변
graph 만들때 boolean[][] 으로 만드는 경우랑 int[][] 나 ArrayList<Integer>[] 로 만드는 기준이 어떻게 되나요?
안녕하세요 🙂 답변을 드렸다고 깜빡하고 늦게 댓글 남깁니다 죄송합니다 ㅠ 질문 주신 내용을 두 가지로 나눠보면 자료형을 boolean으로 할지, int로 할지 구분할 기준이 필요하고,둘째는 이중 배열로 할지, ArrayList를 사용할지 결정할 기준이 필요합니다! boolean vs int: boolean을 사용하는 것이 일반적입니다. 왜냐하면 우리에게 필요한 정보는 두 node 간 연결이 되어있는지 아닌지 알고 싶은 것이라 True/False로 구분만 하면 충분히 정보를 담을 수 있기 때문에 boolean이면 됩니다. 그런데 특정 문제에서는 이를 조금 더 복잡하게 출제해서 '연결되어 있냐/없냐'가 아니라 특정 숫자 값을 넣어서 '해당 칸에서 이동할 때 몇칸씩 이동할지' 등 일반 정보보다 추가되는 정보가 있습니다. 이런 경우는 단순 True/False로 표현할 수 없기 때문에 int로 구분을 해줄 필요가 있습니다. 정리하자면 True/False로만 표현이 가능하면 boolean을 쓰고, 그 외에 추가 정보가 필요하다면 int로 담아줍니다. 그리고 헷갈리신다면 매번 int를 쓰시고, boolean이 필요한 경우에는 0/1로 사용하셔도 됩니다![][] vs ArrayList: 이 경우는 정말 선택인데, [][]는 메모리 낭비가 심한 대신 성능이 빠르고, ArrayList는 성능은 상대적으로 느리지만 메모리가 훨씬 효율적인 장점이 있습니다. 그래서 Node 개수가 1000개 이하일 때는 [][]를 사용해도 메모리가 넉넉하기 때문에 [][]를 써서 빠른 성능을 낼 수 있고, 1000개를 넘어가면 애초에 [][]를 만들기 어렵기 때문에 ArrayList를 사용해야만 합니다. 이 경우에도 굳이 선택하거나 고민하기 싫으시다면 ArrayList를 매번 쓰셔도 동작에 문제가 없을 거에요!
- 1
- 2
- 93
질문&답변
graph
네 맞습니다! 방문한 곳을 재방문하지 않도록 방지하는 visited와, 연결 정보를 가진 graph는 거의 매번 필요하다고 생각하시면 됩니다 🙂 MAX를 두는 건 문제의 최대 개수를 관리하기 위해서 정의합니다. 코드를 최대한 공식처럼 사용하실 수 있도록 MAX라는 변수를 두고, MAX 변수를 문제에서 제공하는 N + 10 으로 설정하시면 되도록 정의했습니다! 그래서 원하시다면 이 값은 필수가 아니라 원하는 값으로 바꾸셔도 됩니다.
- 1
- 1
- 105