├── .gitignore ├── 01_validate_bst.md ├── 02_trie_node.md ├── 03_bst_to_greater_tree.md ├── 04_Depth_of _Binary _tree_AND_Single_Number.md ├── 05_lru_cache.md ├── 06_triple_question.md ├── 07_triple_question2.md ├── 08_triple_question3.md ├── 09_triple_question4.md ├── README.md ├── images ├── 02 │ ├── ar.jpeg │ ├── jz.jpeg │ ├── kh.jpeg │ └── kw.jpeg ├── 03 │ ├── gh.jpeg │ └── jh.jpeg ├── 04 │ ├── aria_01.JPG │ ├── aria_02.JPG │ ├── gw_01.JPG │ ├── gw_02.JPG │ ├── jazz_01.JPG │ └── jazz_02.JPG ├── 05 │ ├── ar.jpeg │ ├── gw.jpeg │ ├── jh.jpeg │ └── kh.jpeg ├── 06 │ ├── 0601.jpg │ ├── 0602.jpg │ ├── 0603.jpg │ ├── 0604.jpg │ └── 0605.jpg ├── 07 │ ├── ar.jpeg │ ├── jh.jpeg │ ├── kh.jpeg │ └── kh2.jpeg └── 09 │ ├── 0901.jpeg │ ├── 0902.jpeg │ ├── 0903.jpeg │ └── 0904.jpeg └── slides └── 190202-complexity.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/vim,osx,linux,windows 3 | # Edit at https://www.gitignore.io/?templates=vim,osx,linux,windows 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | ### OSX ### 21 | # General 22 | .DS_Store 23 | .AppleDouble 24 | .LSOverride 25 | 26 | # Icon must end with two \r 27 | Icon 28 | 29 | # Thumbnails 30 | ._* 31 | 32 | # Files that might appear in the root of a volume 33 | .DocumentRevisions-V100 34 | .fseventsd 35 | .Spotlight-V100 36 | .TemporaryItems 37 | .Trashes 38 | .VolumeIcon.icns 39 | .com.apple.timemachine.donotpresent 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | ### Vim ### 49 | # Swap 50 | [._]*.s[a-v][a-z] 51 | [._]*.sw[a-p] 52 | [._]s[a-rt-v][a-z] 53 | [._]ss[a-gi-z] 54 | [._]sw[a-p] 55 | 56 | # Session 57 | Session.vim 58 | 59 | # Temporary 60 | .netrwhist 61 | # Auto-generated tag files 62 | tags 63 | # Persistent undo 64 | [._]*.un~ 65 | 66 | ### Windows ### 67 | # Windows thumbnail cache files 68 | Thumbs.db 69 | ehthumbs.db 70 | ehthumbs_vista.db 71 | 72 | # Dump file 73 | *.stackdump 74 | 75 | # Folder config file 76 | [Dd]esktop.ini 77 | 78 | # Recycle Bin used on file shares 79 | $RECYCLE.BIN/ 80 | 81 | # Windows Installer files 82 | *.cab 83 | *.msi 84 | *.msix 85 | *.msm 86 | *.msp 87 | 88 | # Windows shortcuts 89 | *.lnk 90 | 91 | # End of https://www.gitignore.io/api/vim,osx,linux,windows 92 | -------------------------------------------------------------------------------- /01_validate_bst.md: -------------------------------------------------------------------------------- 1 | # 1회차 스터디 2 | 2018.12.29(토) 09:00 3 | 4 | 오아리 진행 5 | 6 | 7 | ## 문제 8 | 9 | https://www.hackerrank.com/challenges/is-binary-search-tree/problem?h_r=internal-search 10 | https://leetcode.com/problems/validate-binary-search-tree/ 11 | 12 | 13 | 14 | ## 원숭이들의 생각 15 | ### 경원님 16 | ```javascript 17 | function solution(node) { 18 | const result = left(node) 19 | return result !== -1 20 | } 21 | 22 | function left(node) { 23 | if (!node) { 24 | return true 25 | } 26 | 27 | const leftResult = node.left ? left(node.left) : node.val 28 | const rightResult = node.right ? right(node.right) : node.val 29 | 30 | if (leftResult === -1 || rightResult === -1) { 31 | return -1 32 | } else if (leftResult <= node.val && node.val <= rightResult) { 33 | return rightResult 34 | } else { 35 | return -1 36 | } 37 | } 38 | 39 | function right(node) { 40 | if (!node) { 41 | return true 42 | } 43 | 44 | const leftResult = node.left ? left(node.left) : node.val 45 | const rightResult = node.right ? right(node.right) : node.val 46 | 47 | if (leftResult === -1 || rightResult === -1) { 48 | return -1 49 | } else if (leftResult <= node.val && node.val <= rightResult) { 50 | return leftResult 51 | } else { 52 | return -1 53 | } 54 | } 55 | ``` 56 | 57 | 위 솔루션은 불필요하게 장황한 형태를 하고 있다. 58 | 59 | 거기다 이번 문제를 완전히 해결하지 못한다. 60 | 61 | 트리의 데이터가 더 많아져 깊이가 깊어지면 의도했던 왼쪽에서 가장 큰 값, 오른쪽에서 가장 작은 값을 재귀적으로 반환하지 못할 것이다. 62 | 63 | 가장 먼저 발표를 하면서 처음 시작할때 제약조건을 하나 빼먹으면서 첫 단추를 잘못끼웠는데, 앞으로는 좀 더 문제의 제약조건에 주의할 필요가 있어보인다. 64 | 65 | 66 | 67 | ### 지훈님 68 | 69 | ```kotlin 70 | /** 71 | * Definition for a binary tree node. 72 | * class TreeNode(var `val`: Int = 0) { 73 | * var left: TreeNode? = null 74 | * var right: TreeNode? = null 75 | * } 76 | */ 77 | class Solution { 78 | val bstResults = mutableListOf() 79 | 80 | fun isValidBST(root: TreeNode?): Boolean { 81 | treversal(root) 82 | 83 | return bstResult.none{it == false} 84 | } 85 | 86 | fun treversal(node: TreeNode) { 87 | bstResults.add(isBST(node)) 88 | if (node.left != null) { 89 | treversal(node.left) 90 | } 91 | if (node.right != null) { 92 | treversal(node.right) 93 | } 94 | } 95 | 96 | fun isBST(node: TreeNode) { 97 | return node.value < node.right.value && node.value > node.left.value 98 | } 99 | } 100 | ``` 101 | 102 | * 리프노드일 때, 대비가 안되있음 103 | * 루트노드가 null 일때 대비가 안되있음 104 | * 각 노드가 BST를 만족하더라도, 전체 node가 BST 라는 것을 보장할 수 없음 105 | * 스터디 중에 느낀점 106 | * 설명을 할 때, 중심되는 함수부터 설명을 하자. 107 | * main 함수 내에서 변수와 함수 정의를 먼저 하고 설명하자 108 | * 화이트 보드는 제한적이므로, 공간 활용을 잘 하자 109 | * testSet 을 잘 정의하자 110 | * 테스트를 할때 여분의 공간에 콜스텍을 적으면서 하자 111 | 112 | 113 | 114 | ### 경훈님 115 | 116 | ```java 117 | public class BST_Validate { 118 | 119 | public class TreeNode { 120 | public int val; 121 | public TreeNode left; 122 | public TreeNode right; 123 | } 124 | 125 | public boolean solve(TreeNode n) { 126 | if(n == null) { 127 | return false; 128 | } 129 | 130 | if(n.left != null) { 131 | boolean t = trav(n.left, n.val, -1); 132 | if(t == false) { 133 | return t; 134 | } 135 | } 136 | 137 | if(n.right != null) { 138 | return trav(n.right, 10000, n.val); 139 | } 140 | 141 | return true; 142 | } 143 | 144 | boolean trav(TreeNode n, int max, int min) { 145 | if(n.val < max && n.val > min) { 146 | if(n.left != null) { 147 | boolean t = trav(n.left, n.val, min); 148 | if(t == false) { 149 | return t; 150 | } 151 | } 152 | if(n.right != null) { 153 | return trav(n.right, max, n.val); 154 | } 155 | } 156 | 157 | return false; 158 | } 159 | } 160 | ``` 161 | 162 | * 초기 10분내의 위의 솔루션을 생각해 내지 못함 163 | - 문제는 항상 핵심을 생각하고, 쉽게 생각하자 ! 164 | * 문제를 풀기전에 조건(conditions)을 명확히 파악할것 165 | * complexity 계산방법을 까먹었다. 다시 공부하자. 166 | * 리팩토링 할 중복로직이 안나오도록 연습하자. 167 | - but 모든코드를 극단적으로 줄일려고 하지는 말자 168 | 169 | * [최종 solved code](https://github.com/penpen787/algo_master/commit/d7fdf26c06b59e8360d30c92b8053872e2c5ec78#diff-41193576085bbe743c59b53e069fcb22) 170 | 171 | ### 아리님 172 | 173 | ```java 174 | boolean isBST(Node head) { 175 | if (head == null) { 176 | return true; 177 | } 178 | return checkBST(head, Long.MIN_VALUE, Long.MAX_VALUE); 179 | } 180 | 181 | boolean checkBST(Node node, long min, long max) { 182 | if (node == null) { 183 | return true; 184 | } 185 | int data = node.data; 186 | return (min < data && data < max) && 187 | checkBST(node.left, min, Math.min(max, data)) && checkBST(node.right, Math.max(min, data), max); 188 | } 189 | ``` 190 | 191 | - head에 대해 checkBST를 처음 호출할 때, `Integer.MIN_VALUE`, `Integer.MAX_VALUE`를 호출했었다. 하지만 노드의 val이 integer 범위이므로, 노드의 val이 (각각의 엣지 케이스인) 정수의 최솟값, 최댓값일 때의 경우를 커버하지 못한다. 따라서 checkBST의 min/max 인자의 타입은 int가 아니라 long이어야 한다. 192 | - space complexity를 계산 할 때, call stack도 사용하는 공간으로 계산을 했었다. space complexity는 O(N)이라고 했는데, 생각해보니 평균적으로 트리의 height만큼 스택에 쌓일 것이고 O(logN)이 되겠다. Worst일 때에는 O(N)일테고. 193 | 194 | 195 | 196 | ## 우리가 생각하는 최적의 솔루션 197 | 198 | java 버전으로 하면 아래와 같다. 199 | 200 | ```java 201 | boolean isBST(Node head) { 202 | if (head == null) { 203 | return true; 204 | } 205 | return checkBST(head, Long.MIN_VALUE, Long.MAX_VALUE); 206 | } 207 | 208 | boolean checkBST(Node node, long min, long max) { 209 | if (node == null) { 210 | return true; 211 | } 212 | int data = node.data; 213 | return (min < data && data < max) && 214 | checkBST(node.left, min, Math.min(max, data)) && checkBST(node.right, Math.max(min, data), max); 215 | } 216 | ``` 217 | 트리 내 노드 갯수가 N 개라 할 때, 218 | 219 | 시간 복잡도: O(N) 220 | 221 | 공간 복잡도: O(log N) 222 | -------------------------------------------------------------------------------- /02_trie_node.md: -------------------------------------------------------------------------------- 1 | # 2회차 스터디 2 | 3 | 2019.01.13(일) 09:00 4 | 5 | 김지훈 진행 6 | 7 | 8 | ## 문제 9 | [contacts](https://www.hackerrank.com/challenges/contacts/problem) 10 | 11 | 12 | ## 원숭이들의 생각 13 | ### 경원님 14 | ![solve](./images/02/kw.jpeg) 15 | * 트리 문제라고 무조건 재귀적으로 풀려고 할 필요는 없는 것 같다. 이번 문제처럼 경우에 따라서는 이터레이션하게 푸는 것도 생각해보는게 좋을 것 같다. 16 | * 손코딩에 약한 것 같다. 자꾸 오타가 나고 이전에 작성한 것을 수정하게 된다. 17 | * 기존에 공부했던 기초적인 자료구조들을 다시 한번 구현해보자. 18 | * [after code(재귀를 사용해서 풀이)](https://gist.github.com/kwSeo/5374ca2f01cc12209cf092bb21965f92) 19 | 20 | ### 아리님 21 | ![solve](./images/02/ar.jpeg) 22 | * TrieNode의 children[index]가 null일 경우 새로운 TrieNode()를 할당해주는 곳에 버벅였다. 조금 아쉬운 부분. 23 | * 재밌는 문제였다. 지난 번엔 혼자 해커랭크에서 풀었지만, 이번에는 컨디션도 안좋고 화이트보드 앞에서 코딩하다 보니 손이 매우 떨리고 횡설수설 했다. 24 | * 다른 사람들 앞에서 푼다는 것은 정말 좋은 연습이었던 듯. 25 | 26 | 27 | ### 경훈님 28 | ![solve](./images/02/kh.jpeg) 29 | * 오늘 푼, 문자검색 알고리즘에 대한 컨셉개념이 아예 없었다. 단순한 list & string compare 라니! 30 | * 단순히 brutal force 로 푸는것이 아닌, 스마트함을 보여줄수 있는 컨셉을 찾아내자. 31 | * 단순히 완성만 하는것은 큰 의미가 없을수 있다. 32 | * 많이 풀어서 유형에 좀 익숙해 질 필요가 있다. 33 | 34 | ### 지훈님 35 | ![solve](./images/02/jz.jpeg) 36 | * javascript 함수 동작 설명을 매끄럽게 하지 못했다. 37 | * 함수형 스타일의 장점을 살리지 못한 것 같다. 38 | * t.c, s.c 를 설명할때, 펑션별로 나눠서 설명하는게 좋아보인다. 39 | * 내 구현이 햇갈릴때는 의도를 다시 이야기하고(전달하고), 테스트 케이스를 적어보자 40 | * 테스트 set은 다른색 마커로 쓰면 잘보인다. 41 | 42 | 43 | 44 | ## 우리가 생각하는 최적의 솔루션 45 | 46 | Kotlin 버전으로 하면 아래와 같다. 47 | ```kotlin 48 | private val Char.index: Int 49 | get() = this - 'a' 50 | 51 | class TrieNode { 52 | val children = arrayOfNulls(26) 53 | var cnt = 0 54 | 55 | fun add(c: Char): TrieNode { 56 | if (children[c.index] == null) children[c.index] = TrieNode() 57 | children[c.index]!!.cnt++ 58 | return children[c.index]!! 59 | } 60 | 61 | fun find(c: Char) = children[c.index] ?: TrieNode() 62 | } 63 | 64 | class Trie { 65 | private val root = TrieNode() 66 | 67 | fun add(s: String) { 68 | var currentNode = root 69 | s.forEach { currentNode = currentNode.add(it) } 70 | } 71 | 72 | fun find(s: String): Int { 73 | var currentNode = root 74 | 75 | s.forEach { 76 | currentNode = currentNode.find(it) 77 | } 78 | 79 | return currentNode.cnt 80 | } 81 | } 82 | 83 | fun main(args: Array) { 84 | val n = readLine()!!.toInt() 85 | val root = Trie() 86 | 87 | for (i in 1..n) { 88 | val (op, s) = readLine()!!.split(" ") 89 | when (op) { 90 | "add" -> root.add(s) 91 | "find" -> println(root.find(s)) 92 | } 93 | } 94 | } 95 | ``` 96 | #### 복잡도 97 | * 입력받은 문자열의 길이를 m, 반복회수를 n일때 98 | * add function 99 | * 시간 복잡도: O(nm) 100 | * 공간 복잡도: O(nm) 101 | * find function 102 | * 시간 복잡도: O(nm) 103 | -------------------------------------------------------------------------------- /03_bst_to_greater_tree.md: -------------------------------------------------------------------------------- 1 | # 3회차 스터디 2 | 3 | 2019.01.19(월) 09:00 4 | 5 | 서경원 진행 6 | 7 | 8 | ## 문제 9 | 10 | [Convert BST to Greater Tree](https://leetcode.com/problems/convert-bst-to-greater-tree) 11 | 12 | 13 | ## 원숭이들의 생각 14 | 15 | ### 아리님 16 | 17 | ```java 18 | class Solution { 19 | public TreeNode convertBST(TreeNode node) { 20 | convert(node, 0); 21 | return node; 22 | } 23 | 24 | private int convert(TreeNode node, int acc) { 25 | if(node == null) { 26 | return acc; 27 | } 28 | int right = (node.right == null) ? 0 : convert(node.right, acc); 29 | node.val += right + acc; 30 | return convert(node.left, node.val); 31 | } 32 | } 33 | ``` 34 | 35 | - testcase를 먼저 설명해주면서 visualize 하는 것이 좋았다. 36 | - 재귀 호출 할때 써준 것은 좋았는데, 화살표 보다는 stack trace로 표현해주면 더 좋았을 것 같다. 37 | - 최대한 accumulated value를 parameter로 받아보는 방법으로 풀려고 했는데, left의 right의 right 노드를 디버깅 하다보니, `node.val += right + acc`에서 right와 acc의 차이가 node.val이어서 결국 두 번 더해지는 경우가 있었다. 그래서 멘붕했다. 그 이후로 멘탈 복귀가 어려웠음. 차분히 생각하려 해도 잘 안되더라. 38 | - 재귀 stack trace 따라가는게 생각보다 헷갈린다. 39 | - java에 AtomicInteger라는게 있다! 40 | 41 | 42 | #### 추후 개선된 코드 43 | 44 | ```java 45 | class Solution { 46 | public TreeNode convertBST(TreeNode node) { 47 | convert(node, 0); 48 | return node; 49 | } 50 | 51 | private int convert(TreeNode node, int acc) { 52 | if(node == null) { 53 | return acc; 54 | } 55 | node.val += convert(node.right, acc); 56 | return convert(node.left, node.val); 57 | } 58 | } 59 | ``` 60 | 61 | 노드의 갯수가 N 개라 할 때, 62 | Time complexity: O(N) 63 | Space complexity: O(log N) (O(N) when the worst case) 64 | 65 | 66 | ### 지훈님 67 | 68 | ![jh_solution](./images/03/jh.jpeg) 69 | 70 | * function 시그니쳐를 먼저 적어놓으면 어떨까? 71 | * function 시그니쳐를 기반으로 콜스택을 설명하면 어떨까 72 | * 이게 의도대로 될까? 73 | * input, 행위, output 74 | * 잘못된 풀이로 들어왔을때, 주화입마에 빠져버린다. 75 | * 주어진 노드를 다른 노드로 변형하려했는데, 안 좋은 습관인듯 76 | * 문제가 BST 라고 했으면 분명히 힌트일텐데, 캐치하지 못했다. 77 | * 화이트 보드 코딩을 진행하는 여러 방법이 있을텐데 78 | * 오답이나 산으로 가는 솔류션일지라도 코딩을 해야함 79 | * 시간 안배가 안된다. 시간을 효율적으로 쓰자 80 | * 시간 안배가 안된경우, 내 설계의도를 잘 이야기 하자 81 | * 문제 풀다가 꼬인 케이스일경우, 면접관과 적극적인 커뮤니케이션을 찾자 82 | * 문제 풀다가 틀렸을때는, 틀렸다고 느낀 경우 짧게 시인하고 새 솔루션을 찾자 83 | * 멘탈이 바스라졌을때 탈출이 안된다. 84 | * 모르면 그냥 물어본다. 어짜피 떨어질거... 85 | * 다음주 엑션 포인트 86 | * **알고리즘 표기법 짧게 설명하기** 87 | 88 | 89 | ### 경훈님 90 | 91 | ![gh_solution](./images/03/gh.jpeg) 92 | 93 | * 알고리즘 컨셉잡기 : 1차 SortedList 로 생각하여, 2차 subset sum 으로 개념전개 매우 좋았음 94 | * 코딩 : 머릿속에서 function parameter(signiture) / return 개념을 명확히 잡지 못한상태로 진행하다 헷갈리면 늪에 빠진다. 시작하기 전에 parameter/return 에 대해 꼭 한번 생각하고 시작하자 95 | * 풀이 : 96 | - method stack을 적는것은 좋았으나, 원본트리를 카피하여 변해가는 값을 직접 적으면 좋겠다. 97 | * after 정답like 풀이 : 98 | - static variable 을 사용하는것을 적절히 고려하자, 굉장히 심플하게 풀수 있다. but 알고리즘에선 안티패턴으로 간주할 수도 있다. (그래도 못푸는것보단 푸는게 낫지 않을까?) 99 | - (경원님 link 풀이 후) 문제의 본질을 이용하여, 원래 형태와 다르게 조작 & 생각할수도 있겠다, 문제를 풀고 시간이 남으면(그럴일은 별로 없겠지만..) 더 신박한 방법을 생각해보자 ! 100 | 101 | 102 | ### 경원님 103 | 104 | ```java 105 | class Solution { 106 | public TreeNode convertBST(TreeNode root) { 107 | convert(root, new AtomicInteger(0)); 108 | return root; 109 | } 110 | 111 | public void convert(TreeNode node, AtomicInteger sum) { 112 | if (node == null) { 113 | return; 114 | } 115 | 116 | convert(node.right, sum); 117 | node.val = sum.addAndGet(node.val); 118 | convert(node.left, sum); 119 | } 120 | } 121 | ``` 122 | 123 | * 설명할때 예제 케이스를 미리 그려놓고 로직 흐름에 따라서 어떻게 변해가는지 조금씩 수정해나가면 좋을 것 같다. 124 | * 재귀적인 로직을 설명할때 메모리 구조(heap, stack)을 함께 그려서 설명하면 좋은 것 같다. 125 | * 작성된 로직을 보다 효율적으로 설명할 수 있는 방법들을 생각해보자. 126 | 127 | 128 | ## 최적의 솔루션 129 | 130 | ### AtomicInteger를 활용한 솔루션 131 | 132 | ```java 133 | class Solution { 134 | public TreeNode convertBST(TreeNode root) { 135 | convert(root, new AtomicInteger(0)); 136 | return root; 137 | } 138 | 139 | public void convert(TreeNode node, AtomicInteger sum) { 140 | if (node == null) { 141 | return; 142 | } 143 | 144 | convert(node.right, sum); 145 | node.val = sum.addAndGet(node.val); 146 | convert(node.left, sum); 147 | } 148 | } 149 | ``` 150 | 151 | * 시간 복잡도: O(n) 152 | * 공간 복잡도: O(n) 153 | 154 | ### 반환값을 활용한 솔루션 155 | 156 | ```java 157 | class Solution { 158 | public TreeNode convertBST(TreeNode node) { 159 | convert(node, 0); 160 | return node; 161 | } 162 | 163 | private int convert(TreeNode node, int acc) { 164 | if(node == null) { 165 | return acc; 166 | } 167 | node.val += convert(node.right, acc); 168 | return convert(node.left, node.val); 169 | } 170 | } 171 | ``` 172 | 173 | * 시간 복잡도: O(n) 174 | * 공간 복잡도: O(n) 175 | 176 | ### node link 연결을 통한 솔루션: Reverse Morris In-order Traversal 177 | 178 | * 출처 leetcode solution 179 | * 보다 자세한 설명은 위 문제 링크의 solution 탭 참고 180 | 181 | ```java 182 | class Solution { 183 | /* Get the node with the smallest value greater than this one. */ 184 | private TreeNode getSuccessor(TreeNode node) { 185 | TreeNode succ = node.right; 186 | while (succ.left != null && succ.left != node) { 187 | succ = succ.left; 188 | } 189 | return succ; 190 | } 191 | 192 | public TreeNode convertBST(TreeNode root) { 193 | int sum = 0; 194 | TreeNode node = root; 195 | 196 | while (node != null) { 197 | /* 198 | * If there is no right subtree, then we can visit this node and 199 | * continue traversing left. 200 | */ 201 | if (node.right == null) { 202 | sum += node.val; 203 | node.val = sum; 204 | node = node.left; 205 | } 206 | /* 207 | * If there is a right subtree, then there is at least one node that 208 | * has a greater value than the current one. therefore, we must 209 | * traverse that subtree first. 210 | */ 211 | else { 212 | TreeNode succ = getSuccessor(node); 213 | /* 214 | * If the left subtree is null, then we have never been here before. 215 | */ 216 | if (succ.left == null) { 217 | succ.left = node; 218 | node = node.right; 219 | } 220 | /* 221 | * If there is a left subtree, it is a link that we created on a 222 | * previous pass, so we should unlink it and visit this node. 223 | */ 224 | else { 225 | succ.left = null; 226 | sum += node.val; 227 | node.val = sum; 228 | node = node.left; 229 | } 230 | } 231 | } 232 | 233 | return root; 234 | } 235 | } 236 | ``` 237 | 238 | * 시간 복잡도: O(n) 239 | * 공간 복잡도: O(1) -------------------------------------------------------------------------------- /04_Depth_of _Binary _tree_AND_Single_Number.md: -------------------------------------------------------------------------------- 1 | # 4회차 스터디 2 | 3 | 2019.02.02(토) 09:00 4 | 5 | 전경훈 진행 6 | 7 | 8 | ## 문제 9 | 10 | 1번 - [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree) 11 | 2번 - [Single Number](https://leetcode.com/problems/single-number/) 12 | 13 | ## 원숭이들의 생각 14 | 15 | ### 아리님 16 | * Max depth of binary tree 문제를 재귀적으로 푸는건 쉬우니, iterative 하게 풀어보자 해서, 논리를 설명하는데 queue의 동작을 생각하면서 stack이라 내뱉고 코드까지 작성했다. 조금 더 정신을 차릴 필요가 있겠다. 17 | * single number in array 문제를 풀 때에는 전에 풀어봤던 거라 XOR로 접근하는 방식을 소개했으나, 너무 빠른 최적의 솔루션 전개에 자신감은 있어보이나 이걸 풀어본건지.. 뭔지.. 하는 마음에 다른 문제를 물어봄. 로직 전개에 있어서 소통이 부족했다. 18 | * single number 에서 수식으로 로직을 도출하는 방식이 색달랐다. 경원님 짱. 19 | * 생일이 2주 지났는데에도 축하받았다. 여러분 짱. 20 | ![aria_01](./images/04/aria_01.JPG) 21 | ![aria_02](./images/04/aria_02.JPG) 22 | 23 | 24 | ### 지훈님 25 | 26 | * 문제를 다양한 방법으로 고민하는게 필요하다. 27 | * 어떻게 풀지 설명하고, 예제를 보여준 후, 예상 값을 적고 시작하자 28 | * 아직 문제를 한참 많이 풀어봐야 할 것 같음. 아는 문제가 적다. 29 | * 힌트를 잘 보자. 30 | * 힌트를 무시하는 경향이 있는 것 같다. 31 | * 논리 연산 짱짱맨인듯 32 | 33 | ![jazz_01](./images/04/jazz_01.JPG) 34 | ![jazz_02](./images/04/jazz_02.JPG) 35 | 36 | 37 | ### 경훈님 38 | 1번 : Depth of Binary tree 39 | 2번 : Single Number 40 | * 알고리즘 컨셉잡기 : 1번 문제는 쉽게 컨셉을 잡았으나, 두번째 문제는 아예 컨셉을 잡지 못했다. 원인은 너무 자료구조 측면에서 고민한것 같다. 수학적으로도 고려해보자 ! 41 | * 코딩 : 1번문제는 한방에 잘 풀었음, 2번문제는 Solution을 보고 원리를 이해하여 복기하며 잘 코딩함 42 | * 총평 : 43 | - 2문제를 시간내 풀어내는것은 시간분배차원 & 늪에 빠지는 차원에서 많은 연습이 필요하다. 44 | - 자료구조를 다시 빡세게 공부하고, 어떤 case에 적용해 볼수 있을지 공부하자. 45 | 46 | 47 | ### 경원님 48 | * 알고리즘의 시간/공간 복잡도에 대해서 물어볼 수 있다. 빅오, 세타 등의 표현법을 정확히 알고 있을 필요가 있다. 49 | * 공간/시간 복잡도의 input에 대해서 서로 다른 의견을 가지고 있을 수 있다(예를 들어, 재귀적인 로직에서 함수 콜 스택도 공간복잡도에 포함해야하나?). 시간/공간 복잡도에 대해서 말할때 시간과 공간의 범위를 서로 명확히 할 필요가 있다. 50 | * 이미 알고 문제라고해서 아무런 의사소통 및 고민없이 바로 풀어버리면 오히려 역효과가 날 수 있다. 솔직하게 이미 알고 있는 문제이니 다른 문제를 달라며 자신감을 보이는게 좋을 수도 있다(아니면 적당히 모른척하면서 진행...?) 51 | * 만일 문제가 수식적으로 해결될 것 같다면 수식을 먼저 정리해보자. 52 | * 종종 논리연산(and, or, xor 등)이 매우 유용할때가 있다. 부울식을 다시 한번 정리해보자. 53 | * 설명할때 예제 케이스를 미리 그려놓고 로직 흐름에 따라서 어떻게 변해가는지 조금씩 수정해나가면 좋을 것 같다. 54 | * 재귀적인 로직을 설명할때 메모리 구조(heap, stack)을 함께 그려서 설명하면 좋은 것 같다. 55 | * 작성된 로직을 보다 효율적으로 설명할 수 있는 방법들을 생각해보자. 56 | 57 | ![gw_01](./images/04/gw_01.JPG) 58 | ![gw_02](./images/04/gw_02.JPG) 59 | -------------------------------------------------------------------------------- /05_lru_cache.md: -------------------------------------------------------------------------------- 1 | # 5회차 스터디 2 | 2019.02.09 3 | 오아리 진행 4 | 5 | ## 문제 6 | https://leetcode.com/problems/lru-cache/ 7 | 8 | ## 원숭이들의 회고 9 | ### 지훈스 10 | 11 | ![jh](images/05/jh.jpeg) 12 | 13 | * 문제를 보고 자료구조를 잘 생각해보자. 경우에 따라서는 여러 자료구조가 복합적으로 적용될 수 있다. 14 | * 생각해내기 어렵다면, 기억나는 자료구조를 모두 꺼내 문제랑 매칭시켜보자 15 | * 예제를 잘 적어보자. 16 | * 잘 안풀린다면 예제가 구릴 수도 17 | * 잘 풀리는 경우라도 예제가 편협하게 설정되어있을 수도 있다 18 | * 여전히 문제의 의도를 잘 파악하지 못하는 것 같다. 19 | * 조급하게 보지 말고 천천히 힌트를 확인하자 20 | 21 | ### 경원스 22 | ![gw](images/05/gw.jpeg) 23 | 자료구조를 각각 독립적으로 생각하지 말자. 자료구조는 조합해서 사용하면 보다 효율적으로 사용하고 있다. 24 | * 각 자료구조와 특징과 장점을 잘 이해하고 있을 필요가 있다. 각 자료구조를 조합함으로써 각 자료구조의 장점을 살리고 단점을 줄일 수 있다. 25 | * 때때로 사용하는 프로그래밍 언어에서 제공하는 자료구조 유틸만으로는 기능을 2% 부족할 수 있다. 이때 필요한 핵심 기능만을 직접 구현할 필요가 있을 수 있으니 기본적으로 많이 사용되는 자료구조는 별다른 고민시간없이 뚝딱 작성할 수 있을 필요가 있다. 26 | * heap 자료구조가 잘기억이 나지 않는다. 다시한번 공부해보자. 많이 사용되는 자료구조를 C언어 외에 다른 언어로 다시 구현해보자. 27 | 28 | ### 경훈스 29 | ![gh](images/05/kh.jpeg) 30 | * 알고리즘 컨셉잡기 : LinkedList 를 이용한 Data ordering 컨셉을 잘 잡았다. 문제에서 추가조건이였던 O(1) 을 만족하지는 못하였지만, iterable 하게 풀어내었다. O(n) 31 | * 코딩 : if else 케이스를 처음에 확실하게 생각하지 못한상태로 코딩하니 코드블락이 중구난방이 되었다. if-else concept을 먼저 확실히 생각하고 손코딩하자. 32 | * 총평 : 33 | - leetcode에서 hard 문제 처음도전하였는데, 내가 기존에 알던 지식만으로는 전혀 생각할수 없는 컨셉의 문제였다. 34 | - O(1) 솔루션을 본 후 -> 문제의 핵심이라고 생각했던 O(1) 솔루션인 linkedList(node)를 map으로 searching 하는 아이디어... 단순 경험차원이 아닌, 이 문제의 본질이라고 생각하는것에 더욱 깊게 파고들자. 35 | 36 | ### 아리스 37 | ![ar](images/05/ar.jpeg) 38 | * Time complexity가 O(N)으로 동작하는것으로 처음 생각을 했었다. key의 순서를 singly linked list로 관리하고, get/put 호출이 올 때마다 해당되는 키 값을 뒤로(recently used) 보내고, put에서는 capacity가 꽉 찼을 경우 list의 head 값을 삭제하고, map에서도 삭제하면 된다고 생각했다. 39 | 40 | * Time complexity를 O(1)로 줄일 수는 없을까? 41 | * Singly linked list 대신 key를 담고 있는 array와 pointer를 사용하려고 시도했다. pointer가 가리키는 곳에 key를 담는 것, capacity가 꽉찼을 경우 pointer가 가리키는 곳의 key를 맵에서 삭제하고 새로운 key를 담는 방법을 생각했는데, 그럼 정확히는 O(1)이 아니었다. 그리고 제대로 동작하지 않았다. 왜냐하면, capacity=3인 상황에서 put(1)->put(2)->put(3)->get(3)을 하게 되면 3을 다시 배열 안에서 searching 해야하기 때문이다. 게다가 찾은 키를 맨 앞(index at 0)으로 이동시키는 과정에서의 소요 시간도 필요하기 때문에 오히려 singly linked list로 관리하는게 더 낫다. 42 | 43 | * 멘붕의 시간 도중 엄청난 솔루션을 발견 했다. 44 | [링크 참고](https://leetcode.com/problems/lru-cache/discuss/45911/Java-Hashtable-%2B-Double-linked-list-(with-a-touch-of-pseudo-nodes)) 45 | 46 | * Doubly linked list로 head는 recently used, tail은 leas recently used의 순서로 되어있다. LRU cache 클래스 내부에서는 head와 tail을 항상 가지고 있다. 리스트의 중간에 낀 node를 찾을 때가 문제인데, 그 것을 hashmap을 통해 관리하면 get의 time complexity를 O(1)로 줄일 수 있다. HashMap 을 통해 관리하는 것이 키포인트! 47 | * 키포인트 1. Doubly Linked List를 사용한다. 48 | * 키포인트 2. DLL의 get time complexity를 줄이기 위해 hash map을 사용한다. 49 | 50 | 어떻게 이렇게 생각할 수 있는건지 놀랍기만 할 따름.. 열심히합시다! 51 | 역시 hard는 어렵다. 얕잡아 보지 말것 ㅠ 52 | 53 | ## 최적의 솔루션 54 | [엄청난 솔루션](https://leetcode.com/problems/lru-cache/discuss/45911/Java-Hashtable-%2B-Double-linked-list-(with-a-touch-of-pseudo-nodes)) 55 | ```java 56 | class DLinkedNode { 57 | int key; 58 | int value; 59 | DLinkedNode pre; 60 | DLinkedNode post; 61 | } 62 | 63 | /** 64 | * Always add the new node right after head; 65 | */ 66 | private void addNode(DLinkedNode node){ 67 | node.pre = head; 68 | node.post = head.post; 69 | 70 | head.post.pre = node; 71 | head.post = node; 72 | } 73 | 74 | /** 75 | * Remove an existing node from the linked list. 76 | */ 77 | private void removeNode(DLinkedNode node){ 78 | DLinkedNode pre = node.pre; 79 | DLinkedNode post = node.post; 80 | 81 | pre.post = post; 82 | post.pre = pre; 83 | } 84 | 85 | /** 86 | * Move certain node in between to the head. 87 | */ 88 | private void moveToHead(DLinkedNode node){ 89 | this.removeNode(node); 90 | this.addNode(node); 91 | } 92 | 93 | // pop the current tail. 94 | private DLinkedNode popTail(){ 95 | DLinkedNode res = tail.pre; 96 | this.removeNode(res); 97 | return res; 98 | } 99 | 100 | private Hashtable 101 | cache = new Hashtable(); 102 | private int count; 103 | private int capacity; 104 | private DLinkedNode head, tail; 105 | 106 | public LRUCache(int capacity) { 107 | this.count = 0; 108 | this.capacity = capacity; 109 | 110 | head = new DLinkedNode(); 111 | head.pre = null; 112 | 113 | tail = new DLinkedNode(); 114 | tail.post = null; 115 | 116 | head.post = tail; 117 | tail.pre = head; 118 | } 119 | 120 | public int get(int key) { 121 | 122 | DLinkedNode node = cache.get(key); 123 | if(node == null){ 124 | return -1; // should raise exception here. 125 | } 126 | 127 | // move the accessed node to the head; 128 | this.moveToHead(node); 129 | 130 | return node.value; 131 | } 132 | 133 | 134 | public void set(int key, int value) { 135 | DLinkedNode node = cache.get(key); 136 | 137 | if(node == null){ 138 | 139 | DLinkedNode newNode = new DLinkedNode(); 140 | newNode.key = key; 141 | newNode.value = value; 142 | 143 | this.cache.put(key, newNode); 144 | this.addNode(newNode); 145 | 146 | ++count; 147 | 148 | if(count > capacity){ 149 | // pop the tail 150 | DLinkedNode tail = this.popTail(); 151 | this.cache.remove(tail.key); 152 | --count; 153 | } 154 | }else{ 155 | // update the value. 156 | node.value = value; 157 | this.moveToHead(node); 158 | } 159 | 160 | } 161 | ``` 162 | -------------------------------------------------------------------------------- /06_triple_question.md: -------------------------------------------------------------------------------- 1 | # 6회차 스터 2 | 2019.03.03 3 | 김지훈 진행 4 | ## 문제 5 | 각자 다른 문제! 6 | 7 | ## 원숭이들의 회고 8 | ### 경훈님 9 | 푼 문제 : number encoding 10 | * 알고리즘 컨셉잡기 : 처음엔 #, () 캉태에 대한 컨디션 불리안을 설정해보려고 미궁에 빠짐. but 피드백 후, 바로 변경하여 #, (), 숫자 세 문자로 분리하여 처리하는 방법 고안 11 | * 코딩 : for loop의 counter 조작을 잘 처리함, 이전 숫자값 기억을 위해 memory 를 사용함 12 | * 총평 : 13 | - number(숫자 + #숫자)의 대한 처리와 multiply() 처리를 분하면 memory 기억이 필요없음 14 | - 굳이 내가 기존에 알고있던 자료구조에 끼워맞출 필요는 없다 ! 15 | 16 | 17 | ### 아리님 18 | 푼 문제: [read a number in english](https://leetcode.com/problems/integer-to-english-words/) 19 | * 한 번 봤던 문제라 기억을 더듬 더듬하며 해나갔다. 20 | * 문제를 보고 바로 코드를 작성하려고 하지 말고, 패턴을 찾아보자. 도움이 될 만한 패턴이 보이는가? 21 | * 그걸 토대로 모듈화를 시도해보자. 22 | * 엣지 케이스를 반드시 고려하자. 23 | 24 | ![img](images/06/0604.jpg) 25 | ![img](images/06/0605.jpg) 26 | 27 | 28 | ### 경원님 29 | 푼 문제: [문제 이름이 뭔지 모름, 뭐라고 불러야 할지도 모름(지훈형이 잘 알 것이다)](https://leetcode.com/problems/decode-string/) 30 | * 문제를 풀기전 여러 케이스에 대해서 검토해보자. 31 | * 뭔가 이상하게? 문제가 간단하기 해결되는 것 같으면 의심을 해보자. 함정에 빠지고 있는 것일 수 있다. 32 | * 이번에 푼 문제는 stack을 사용하면 깔끔하게 작성할 수 있다. 자료구조를 사용하는 감각을 기를 필요가 있어보인다. 33 | 34 | ### 지훈님 35 | 이번에는 서로 다른 문제를 풀어보기 위해 문제를 3개 골랐음. 36 | 문제 고르고 먼저 풀어보는 공수가 있지만, 나쁘지 않은 시도였다고 생각 37 | 38 | ![img](images/06/0601.jpg) 39 | ![img](images/06/0602.jpg) 40 | ![img](images/06/0603.jpg) 41 | -------------------------------------------------------------------------------- /07_triple_question2.md: -------------------------------------------------------------------------------- 1 | # 6회차 스터 2 | 2019.03.16 3 | 서경원 진행 4 | 5 | ## 문제 6 | 각자 다른 문제!! 7 | 8 | ## 원숭이들의 회고 9 | ### 지훈님 10 | #### 푼 문제: number shuffle 11 | 0부터 100사이의 숫자가 주어졌을 때 12 | n번 shuffle을 수행하고 나서 가장 앞에 있는 숫자는 무엇인가? 13 | 카드를 선택할 수 없다면 -1을 반환한다. 14 | 15 | shuffle 방법 - numbers = 1~10, n = 2 16 | - 1 2 3 4 5 6 7 8 9 10 17 | - 3 4 5 6 7 8 1 2 9 10 18 | - 5 6 3 4 7 8 1 2 9 10 19 | - return 5 20 | 21 | ![img_jh](images/07/jh.jpeg) 22 | 23 | #### 후기 24 | * 오늘 쉬운 문제 걸림 25 | * if 문 condition에서 살짝 뇌절이 옴 26 | * 햇갈리면 샘플을 적자 27 | * 문제 자체가 함정일 수 있다. 재귀일지, 이터레이터일지. 28 | * 문제의 사전조건을 확인하는 것은 잘 했다. 29 | * 힌트주면 바로 다음거로 남은거로 넘어가자.(힌트 주면 니꺼 지금 잘못하고있는거임) 30 | 31 | ### 아리님 32 | #### 푼 문제: 허프만 디코딩 33 | 허프만 트리와 허프만 인코딩된 코드가 주어졌을때 디코딩을 수행하는 함수를 구현하시오. 34 | 35 | **허프만 트리 노드** 36 | ```java 37 | class Node { 38 | public int frequency; 39 | public char data; 40 | public Node left, right; 41 | } 42 | ``` 43 | 44 | ![img_ar](images/07/ar.jpeg) 45 | 46 | #### 후기 47 | - 허프만 트리만 듣고 좌절할 뻔 했다. 48 | - 1101이 있을때, 1만 쪼개야 하나 11로 쪼개서 디코딩을 해야하나 헷갈렸는데, 허프만 트리의 특징을 다시 한 번 상기하니 겹칠 일이 없다는 것을 알게됐다.(이건 좀 짱인듯) 49 | - 평소라면 못풀었을 문제인데, 그날은 왜인지 모르게 잘 풀렸다. 꾸준함의 효과인가! 라는 자만감과 함께 퇴장.. 50 | 51 | ### 경훈님 52 | #### 푼 문제: 순환 리스트 체크 53 | 리스트가 있을 때 순환 리스트인지 확인하는 함수를 작성하시오. 54 | 55 | **리스트 노드** 56 | ```java 57 | class ListNode { 58 | int value; 59 | ListNode next; 60 | } 61 | ``` 62 | 63 | ![img_kh](images/07/kh.jpeg) 64 | 65 | #### 후기 66 | - Case 정리를 잘 하자, closed, self-one-node-cycle 등 67 | - mutable 조건을 체크하자. 처음 생각한 Set 이외에 방법은 모두 mutable 조건이였다. 68 | 69 | ### 최적의 솔루션 70 | #### number shuffle 71 | ```java 72 | public int solve(List nums, int m) { 73 | if (nums == null) { 74 | return -1; 75 | } 76 | int size = nums.size(); 77 | if (size == 0) { 78 | return -1; 79 | } else if (size <= m * 2 || m == 0) { 80 | return nums.get(0); 81 | } else { 82 | return solve(nums.subList(m, size - m), m); 83 | } 84 | } 85 | ``` 86 | 87 | #### 허프만 디코딩 88 | ```java 89 | String decode(String s, Node root) { 90 | StringBuilder sb = new StringBuilder(); 91 | Node current = root; 92 | for (char ch : s.toCharArray()) { 93 | if (ch == '0') { 94 | current = current.left; 95 | } else { 96 | current = current.right; 97 | } 98 | 99 | if (current.left == null && current.right == null) { 100 | sb.append(current.data); 101 | current = root; 102 | } 103 | } 104 | return sb.toString(); 105 | } 106 | ``` 107 | 108 | #### 순환 리스트 체크 109 | ```java 110 | public boolean solve(ListNode items) { 111 | ListNode faster = items, slower = items; 112 | while (faster != null && faster.next != null) { 113 | faster = faster.next.next; 114 | slower = slower.next; 115 | if (faster == slower) { 116 | return true; 117 | } 118 | } 119 | return false; 120 | } 121 | ``` -------------------------------------------------------------------------------- /08_triple_question3.md: -------------------------------------------------------------------------------- 1 | # 8회차 스터디 2 | 2019.03.31 3 | 전경훈 진행 4 | 5 | ## 문제 6 | EASY 난이도 3문제를 모두 빠르게 풀어보기 7 | 8 | ## 원숭이들의 회고 9 | ### 경훈님 10 | 내가 현회사에 입사할때 경험처럼, 3문제 정도를 모두 알려준 후, 얼마나 빠르게 & 많이 풀수 있는지 확인해보는 연습을 해보자 ! 11 | 12 | ## 지훈님 13 | ### Problem 14 | * 문제가 3개였는데 15 | * [invert binary tree](https://leetcode.com/problems/invert-binary-tree/) 16 | * [toeplitz matrix](https://leetcode.com/problems/toeplitz-matrix/) 17 | * [merge two binary tree](https://leetcode.com/problems/merge-two-binary-trees/) 18 | * 이 문제들을 제한시간 안에 생각하고, 가장 자신 있는 문제를 앞에서 풀기로 했다. 19 | * 내가 선택한 문제는 `merge two binary tree` 20 | 21 | ``` 22 | Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. 23 | 24 | You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree. 25 | ``` 26 | 27 | ### Solve 28 | ``` 29 | <사진 & 직접수정 예정> 30 | ``` 31 | 32 | ### 회고 33 | * 시간안에 3개의 문제를 푸는게 꽤 힘들었다. 34 | * idea를 빠르게 생각하고 검증하고, 문제가 있는지 찾은 후 다음문제로 넘어갔다. 35 | * 다행히 생각이 빠르게 정리되어 문제를 쉽게 풀 수 있었음 36 | * 한참 쓰다가, condition 이 너무 햇갈린다. 37 | * 침착하게 문제 상황을 주석으로 달면서 정리하자. 38 | * 우왕좌왕 하면 시간만 흐른다. 39 | 40 | ## 아리님 41 | ### Problem 42 | 3 문제를 제한 시간 안에 생각하고, [Toeplitz matrix](https://leetcode.com/problems/toeplitz-matrix/)문제를 발표했다. 43 | ``` 44 | A matrix is Toeplitz if every diagonal from top-left to bottom-right has the same element. 45 | 46 | Now given an M x N matrix, return True if and only if the matrix is Toeplitz. 47 | ``` 48 | 49 | ### Solution 50 | ```java 51 | class Solution { 52 | public boolean isToeplitzMatrix(int[][] matrix) { 53 | final int COL = matrix[0].length; 54 | for(int r = 0; r < matrix.length - 1; ++r){ 55 | for(int c = 0; c < COL - 1; ++c){ 56 | if(matrix[r][c] != matrix[r + 1][c + 1]) { 57 | return false; 58 | } 59 | } 60 | } 61 | return true; 62 | } 63 | } 64 | ``` 65 | 66 | ### 회고 67 | - brute force하게 포인터를 이동해가며 찾는 방법으로 로직을 전개 68 | - 면접관이 준 힌트를 얻어 위의 솔루션을 도출(sliding window) 69 | - 힌트를 빠르게 캐치한 것이 잘한 것 70 | 71 | 72 | ## 경원님 73 | 74 | ### 75 | - 첫 단추를 잘못끼웠다. 재귀적으로 문제를 해결할 때 결과를 반환받아서 조합하는 방식이 아닌 결과 객체를 미리 생성하고 데이터를 누적하면서 만들어 나가는 방식으로 했더니 갑자기 문제가 복잡해졌다. 중간 중간에 다른분들이 힌트를 주신 것 같은데 내가 고집을 부린 것은 아닐까 싶다... 76 | - 오늘 풀었던 방식 말고 재귀적으로 호출된 결과를 조합하는 방식으로 다시 풀어보자. 코드가 훨씬 간단해 질 것이다. 77 | - 어떤 방법을 바꾸려고 할 때 불필요하게 많은 부분을 제거하여 나중에 코드를 다시 작성할 때 불필요한 시간을 소비했다. 침착하게 정말 수정이 필요한 부분을 파악하여 조금씩 수정해 나가자. 78 | - nullable한 객체가 많아지니 은근히 복잡해진다.... 79 | 80 | #### 푼 문제 81 | - Invert Binary Tree 82 | - is Toeplitz Matrix? 83 | - **Merge Two Binary Trees** 84 | - 내가 선택한 문제 85 | 86 | ```java 87 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { 88 | if (t1 == null && t2 == null) { 89 | return null; 90 | } 91 | TreeNode result = new TreeNode(0); 92 | mergeTrees(t1, t2, result); 93 | return result; 94 | } 95 | 96 | public void mergeTrees(TreeNode t1, TreeNode t2, TreeNode result) { 97 | if (t1 != null && t2 != null) { 98 | result.val = t1.val + t2.val; 99 | if (t1.left != null || t2.left != null) { 100 | result.left = new TreeNode(0); 101 | mergeTrees(t1.left, t2.left, result.left); 102 | } 103 | if (t1.right != null || t2.right != null) { 104 | result.right = new TreeNode(0); 105 | mergeTrees(t1.right, t2.right, result.right); 106 | } 107 | } else if (t1 != null) { 108 | result.val = t1.val; 109 | if (t1.left != null) { 110 | result.left = new TreeNode(0); 111 | mergeTrees(t1.left, null, result.left); 112 | } 113 | if (t1.right != null) { 114 | result.right = new TreeNode(0); 115 | mergeTrees(null, t1.right, result.right); 116 | } 117 | } else if (t2 != null) { 118 | result.val = t2.val; 119 | if (t2.left != null) { 120 | result.left = new TreeNode(0); 121 | mergeTrees(t2.left, null, result.left); 122 | } 123 | if (t2.right != null) { 124 | result.right = new TreeNode(0); 125 | mergeTrees(t2.right, null, result.right); 126 | } 127 | } 128 | } 129 | ``` 130 | -------------------------------------------------------------------------------- /09_triple_question4.md: -------------------------------------------------------------------------------- 1 | # 9회차 스터디 2 | 2019.04.06 오아리 진행 3 | 4 | # 문제 5 | 세 문제를 화이트보드에 적은 뒤, 각자 한 문제씩 선택하여 종이에 적는 시간 없이 바로 문제 풀이 진행. 6 | - [Cousins in Binary Tree](https://leetcode.com/problems/cousins-in-binary-tree/) 7 | - [Trim BST](https://leetcode.com/problems/trim-a-binary-search-tree/) 8 | - [factorial-trailing-zeroes](https://leetcode.com/problems/factorial-trailing-zeroes) 9 | 10 | # 원숭이들의 생각 11 | ## 경원님 12 | 13 | ![img](images/09/0901.jpeg) 14 | 15 | ### Problem 16 | 17 | [한 트리 내에 주어진 두 노드는 사촌 노드인가?](https://leetcode.com/problems/cousins-in-binary-tree/) 18 | 19 | ### Solution 20 | ```java 21 | public static final Result NOT_FOUND = new Result(null, 0); 22 | 23 | public boolean isCousins(TreeNode root, int x, int y) { 24 | Result xResult = find(null, root, x, 1); 25 | Result yResult = find(null, root, y, 1); 26 | return xResult.parent != null 27 | && yResult.parent != null 28 | && xResult.parent != yResult.parent 29 | && xResult.depth == yResult.depth; 30 | } 31 | 32 | Result find(TreeNode parent, TreeNode node, int v, int depth) { 33 | if (node == null) { 34 | return NOT_FOUND; 35 | } else if (node.val == v) { 36 | return new Result(parent, depth); 37 | } else { 38 | Result leftResult = find(node, node.left, v, depth + 1); 39 | Result rightResult = find(node, node.right, v, depth + 1); 40 | return leftResult == NOT_FOUND ? rightResult : leftResult; 41 | } 42 | } 43 | ``` 44 | 45 | ### 회고 46 | - 오늘은 컨디션이 좋아서 수월하게 문제가 풀렸다. 하지만 언제나 컨디션이 좋을 수는 없으니(대부분의 날이 컨디션이 안좋으니...) 큰 문제없었다고 우쭐해서는 안된다. 47 | - 조금이라도 문제에 수학적인 부분이 들어가기 시작하면 매우 힘들어지는 것이 느껴진다. 역시 알고리즘 실력을 늘릴려면 추가적인 수학 공부도 필요한 모양이다. 48 | 49 | ## 경훈님 50 | ![img](images/09/0903.jpeg) 51 | 52 | ### Problem 53 | 54 | [factorial-trailing-zeroes](https://leetcode.com/problems/factorial-trailing-zeroes) 55 | 56 | ### Solution 57 | 58 | ```java 59 | 60 | ``` 61 | 62 | ### 회고 63 | - 초반 규칙찾는데 실패하여 문제를 정확히 풀어내지 못하였다. 64 | - 2,5, 짝수&홀수 등 special number로 규칙을 찾으려 했는데 머리속만 복잡해질 뿐 규칙을 찾기 못하였다. 65 | - 이번문제의 핵심은 2-5의 곱이 10이 된다는 것 ! 66 | - 생각이 중간에 꼬이면, *처음부터 다시 1부터 케이스로 생각해보자.* 67 | - TODO : 수학적 증명 68 | 69 | 70 | 71 | ## 지훈님 72 | ![img](images/09/0902.jpeg) 73 | 74 | ### Problem 75 | 76 | [Trim BST](https://leetcode.com/problems/trim-a-binary-search-tree/) 77 | ``` 78 | Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that all its elements lies in [L, R] (R >= L). You might need to change the root of the tree, so the result should return the new root of the trimmed binary search tree. 79 | ``` 80 | 81 | ### Solution 82 | ``` 83 | <사진쓰, 마크다운을 제가 직접 수정할게염> 84 | ``` 85 | 86 | ### 회고 87 | - 지난주와 마찬가지로 condition 적다가 뇌절이 오는 것 같다. 88 | - 평소보다 더 집중해서 침착해야 한다. 89 | - 엣지 케이스에 테스트를 잘 정리해서 이야기 하지 못한 것 같다. 90 | 91 | 92 | 93 | --- 94 | 95 | ![img](images/09/0904.jpeg) 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 원숭이를 구하라! 2 | 저희는 원숭이:monkey: :monkey: :monkey: :monkey: 입니다. 불쌍한 원숭이들이 자유로워지도록 문제 속에서 구해주세요. 3 | 4 | ## 취지 5 | 문제 해결 능력을 키우자! 6 | 7 | 8 | ## 진행 방향 9 | 10 | ### 문제 선정(5분) 11 | - [해커랭크](https://hackerrank.com) 12 | - [리트코드](http://leetcode.com) 13 | - [백준](https://www.acmicpc.net/problemset) 14 | - 책 _Cracking the Coding Interview_ 15 | 16 | ### 풀이(70분) 17 | - 각자 로직 생각(10분) 18 | - 화이트 보드 코딩 및 피드백(인당 10-15분) 19 | - 타이머로 시간 체크 20 | 21 | ### 피드백(15분) 22 | - 문제 난이도에 대한 피드백 23 | - 기타 알게된 것들 24 | 25 | ### 정리(30분) 26 | - 최적의 솔루션을 공유 27 | - 이야기 28 | 29 | 30 | ## 정기 모임일 31 | 시간: 12/29일 부터 **매주 토요일 9시**(20회 진행) 32 | 33 | 장소: 판교 어딘가 34 | 35 | ## 규칙 36 | - 그날의 스터디 진행자가 있습니다. 37 | ``` 38 | 스터디 진행자가 할 일 39 | - 참여 인원 및 장소 확정 40 | - 문제 결정 권한(문제를 정하기 어렵다면 구성원들이 도움을 줄 수 있음) 41 | - 깃헙에 오늘의 스터디 정리(푼 문제, 각자의 솔루션, 회고) 42 | ``` 43 | - 풀고 싶은 문제가 있다면 가져오세요! 44 | - 컨셉에 대해 미리 공유해주셔도 좋습니다!(e.g. backtracking 관련한 문제를 풀거라면, backtracking에 대한 간략한 링크 or 언질!) 45 | - 모두가 잘하지 못하므로 모두가 캐리해야 합니다 ㅎㅎ 46 | - 20회 끝나는날 같이 submit, 그리고 맥주 :beer: 47 | 48 | --- 49 | ## 정리 템플릿 50 | 어떻게 정리하지? 싶다면 아래의 템플릿을 참고하세요! 51 | 52 | 파일명은 `{N}_{문제제목}.md` 로 부탁해요! 53 | 54 | ``` 55 | # {N}회차 스터디 56 | {yyyy. MM. dd} 57 | {스터디 진행자 이름} 58 | 59 | ## 문제 60 | {문제 설명} 61 | {문제 링크} 62 | 63 | ## 원숭이들의 생각 64 | ### {참여자1 이름} 65 | {참여자1 솔루션} 66 | 67 | ### {참여자2 이름} 68 | {참여자2 솔루션} 69 | 70 | ### {참여자3 이름} 71 | {참여자3 솔루션} 72 | 73 | ### {참여자4 이름} 74 | {참여자4 솔루션} 75 | 76 | ## 최적의 솔루션 77 | {솔루션 코드} 78 | 79 | ## 원숭이들의 회고 80 | {회고 내용} 81 | ``` 82 | -------------------------------------------------------------------------------- /images/02/ar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/02/ar.jpeg -------------------------------------------------------------------------------- /images/02/jz.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/02/jz.jpeg -------------------------------------------------------------------------------- /images/02/kh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/02/kh.jpeg -------------------------------------------------------------------------------- /images/02/kw.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/02/kw.jpeg -------------------------------------------------------------------------------- /images/03/gh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/03/gh.jpeg -------------------------------------------------------------------------------- /images/03/jh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/03/jh.jpeg -------------------------------------------------------------------------------- /images/04/aria_01.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/aria_01.JPG -------------------------------------------------------------------------------- /images/04/aria_02.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/aria_02.JPG -------------------------------------------------------------------------------- /images/04/gw_01.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/gw_01.JPG -------------------------------------------------------------------------------- /images/04/gw_02.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/gw_02.JPG -------------------------------------------------------------------------------- /images/04/jazz_01.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/jazz_01.JPG -------------------------------------------------------------------------------- /images/04/jazz_02.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/04/jazz_02.JPG -------------------------------------------------------------------------------- /images/05/ar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/05/ar.jpeg -------------------------------------------------------------------------------- /images/05/gw.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/05/gw.jpeg -------------------------------------------------------------------------------- /images/05/jh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/05/jh.jpeg -------------------------------------------------------------------------------- /images/05/kh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/05/kh.jpeg -------------------------------------------------------------------------------- /images/06/0601.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/06/0601.jpg -------------------------------------------------------------------------------- /images/06/0602.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/06/0602.jpg -------------------------------------------------------------------------------- /images/06/0603.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/06/0603.jpg -------------------------------------------------------------------------------- /images/06/0604.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/06/0604.jpg -------------------------------------------------------------------------------- /images/06/0605.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/06/0605.jpg -------------------------------------------------------------------------------- /images/07/ar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/07/ar.jpeg -------------------------------------------------------------------------------- /images/07/jh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/07/jh.jpeg -------------------------------------------------------------------------------- /images/07/kh.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/07/kh.jpeg -------------------------------------------------------------------------------- /images/07/kh2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/07/kh2.jpeg -------------------------------------------------------------------------------- /images/09/0901.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/09/0901.jpeg -------------------------------------------------------------------------------- /images/09/0902.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/09/0902.jpeg -------------------------------------------------------------------------------- /images/09/0903.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/09/0903.jpeg -------------------------------------------------------------------------------- /images/09/0904.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/images/09/0904.jpeg -------------------------------------------------------------------------------- /slides/190202-complexity.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeys-code/save-the-monkey/7a61cabfb57193052b86856f8394088406b3980b/slides/190202-complexity.pdf --------------------------------------------------------------------------------