From 637f055b86738dcf8d04c137d0b9df796695262f Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Wed, 20 Sep 2023 01:35:14 +0900 Subject: [PATCH 01/10] =?UTF-8?q?problem-1=20bubble=20=EC=A0=95=EB=A0=AC?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/problem-1.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/problem-1/problem-1.test.js b/problem-1/problem-1.test.js index f54f840..7c3f8c4 100644 --- a/problem-1/problem-1.test.js +++ b/problem-1/problem-1.test.js @@ -1,4 +1,17 @@ const bubbleSort = (array) => { + // i = 정렬이 완료될 원소의 개수 + // 첫 패스 때 1개의 정렬이 완료됨 + // 마지막 패스 때 array.length - 1개의 원소가 정렬됨 + // array.length - 1개가 원소가 정렬되면 마지막 원소는 정렬할 필요가 없다. + for (let i = 1; i < array.length; i++) { + for (let j = 0; j < array.length - i; j++) { + if (array[j] > array[j + 1]) { + const temp = array[j + 1]; + array[j + 1] = array[j]; + array[j] = temp; + } + } + } }; test.each([ From 47bad78b28d7f322cf2d1d29e0bf1445e792f93c Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Fri, 22 Sep 2023 00:02:13 +0900 Subject: [PATCH 02/10] refactor: problem-1 --- problem-1/problem-1.test.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/problem-1/problem-1.test.js b/problem-1/problem-1.test.js index 7c3f8c4..f049e24 100644 --- a/problem-1/problem-1.test.js +++ b/problem-1/problem-1.test.js @@ -3,12 +3,10 @@ const bubbleSort = (array) => { // 첫 패스 때 1개의 정렬이 완료됨 // 마지막 패스 때 array.length - 1개의 원소가 정렬됨 // array.length - 1개가 원소가 정렬되면 마지막 원소는 정렬할 필요가 없다. - for (let i = 1; i < array.length; i++) { - for (let j = 0; j < array.length - i; j++) { + for (let i = 0; i < array.length; i++) { + for (let j = 0; j < array.length - 1 - i; j++) { if (array[j] > array[j + 1]) { - const temp = array[j + 1]; - array[j + 1] = array[j]; - array[j] = temp; + [array[j + 1], array[j]] = [array[j], array[j + 1]]; } } } From 80e65c086664109fe23ad4efb475796d39a029f5 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Fri, 22 Sep 2023 00:04:05 +0900 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20problem-1=20=EC=9D=B4=EB=AF=B8=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC=EB=90=98=EC=96=B4=EC=9E=88=EC=9D=84=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=B2=AB=20=ED=8C=A8=EC=8A=A4=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=95=A8=EC=88=98=20=EC=A2=85=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/problem-1.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/problem-1/problem-1.test.js b/problem-1/problem-1.test.js index f049e24..e558b0b 100644 --- a/problem-1/problem-1.test.js +++ b/problem-1/problem-1.test.js @@ -1,4 +1,6 @@ const bubbleSort = (array) => { + let exchangeCount = 0; + // i = 정렬이 완료될 원소의 개수 // 첫 패스 때 1개의 정렬이 완료됨 // 마지막 패스 때 array.length - 1개의 원소가 정렬됨 @@ -6,9 +8,15 @@ const bubbleSort = (array) => { for (let i = 0; i < array.length; i++) { for (let j = 0; j < array.length - 1 - i; j++) { if (array[j] > array[j + 1]) { + exchangeCount += 1; + [array[j + 1], array[j]] = [array[j], array[j + 1]]; } } + + if (i === 0 && exchangeCount === 0) { + return; + } } }; From 4952967d133a525eb21c6d1335cbcb8bc2dfc264 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Fri, 22 Sep 2023 00:18:32 +0900 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20problem-2=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/problem-2.test.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/problem-2/problem-2.test.js b/problem-2/problem-2.test.js index 1e1fe4f..469f324 100644 --- a/problem-2/problem-2.test.js +++ b/problem-2/problem-2.test.js @@ -1,4 +1,29 @@ +const exchange = (array, a, b) => { + [array[b], array[a]] = [array[a], array[b]]; +}; + +const less = (a, b) => a < b; + +const findMinIndex = (array, startIndex) => { + let minIndex = startIndex; + + for (let i = startIndex; i < array.length; i++) { + if (less(array[i], array[minIndex])) { + minIndex = i; + } + } + + return minIndex; +}; + const selectionSort = (array) => { + for (let i = 0; i < array.length - 1; i++) { + const minIndex = findMinIndex(array, i); + + if (i !== minIndex) { + exchange(array, i, minIndex); + } + } }; test.each([ From 2c62aa5ebe2303ff4ca628de705ecd79ca675313 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Fri, 22 Sep 2023 00:44:10 +0900 Subject: [PATCH 05/10] =?UTF-8?q?feat:=20problem-2=20=EC=82=BD=EC=9E=85=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-3/problem-3.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/problem-3/problem-3.test.js b/problem-3/problem-3.test.js index e4450b5..abf46bb 100644 --- a/problem-3/problem-3.test.js +++ b/problem-3/problem-3.test.js @@ -1,4 +1,19 @@ +const exchange = (array, a, b) => { + [array[b], array[a]] = [array[a], array[b]]; +}; + +const less = (a, b) => a < b; + const insertionSort = (array) => { + for (let i = 1; i < array.length; i++) { + for (let j = i; j > 0; j--) { + if (less(array[j], array[j - 1])) { + exchange(array, j, j - 1); + } else { + break; + } + } + } }; test.each([ From fdfc313d2eda570a9c6e96fc74488fef7100ab21 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Mon, 25 Sep 2023 20:17:39 +0900 Subject: [PATCH 06/10] =?UTF-8?q?feat:=20problem-4=20=EC=85=B8=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-4/problem-4.test.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/problem-4/problem-4.test.js b/problem-4/problem-4.test.js index 069ccdf..15b519a 100644 --- a/problem-4/problem-4.test.js +++ b/problem-4/problem-4.test.js @@ -1,4 +1,26 @@ -const shellSort = (array) => { +const exchange = (list, a, b) => { + [list[b], list[a]] = [list[a], list[b]]; +}; + +const less = (a, b) => a < b; + +const shellSort = (list) => { + let h = 1; + const { length } = list; + + while (h < (length / 3)) { + h = (3 * h) + 1; + } + + for (let k = h; k >= 1; k = Math.floor(k / 3)) { + for (let i = k; i < length; i++) { + for (let j = i; j >= k; j--) { + if (less(list[j], list[j - k])) { + exchange(list, j, j - k); + } + } + } + } }; test.each([ From 6308782ae0192994225648b6d8700d97b784e599 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Thu, 28 Sep 2023 16:43:23 +0900 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20problem-6=20quick=20sort=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-6/problem-6.test.js | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/problem-6/problem-6.test.js b/problem-6/problem-6.test.js index f335a1f..8adc1bc 100644 --- a/problem-6/problem-6.test.js +++ b/problem-6/problem-6.test.js @@ -1,4 +1,69 @@ -const quickSort = (array) => { +const exchange = (array, a, b) => { + [array[b], array[a]] = [array[a], array[b]]; +}; + +/** + * 1. 하나의 배열에 대해서 퀵 정렬을 실행 + * 2. pivot의 위치를 결정한다 + * 3. pivot의 위치를 기준으로 왼쪽, 오른쪽 부분 배열을 만든다 + * 4. 왼쪽, 오른쪽 부분 배열에 대해서 퀵 정렬을 실행한다 + */ +const quickSort = (array, start, end) => { + const startIndex = start || 0; + const endIndex = end || array.length - 1; + + const length = endIndex - startIndex + 1; + + if (length <= 1) { + return; + } + + const pivot = array[startIndex]; + + let left = startIndex; + let right = endIndex; + + while (right > left) { + for (left; left <= endIndex; left++) { + if (pivot < array[left]) { + break; + } + } + + if (left > endIndex) { + left = endIndex; + } + + for (right; right >= startIndex; right--) { + if (pivot >= array[right]) { + break; + } + } + + if (right < startIndex) { + right = startIndex; + } + + if (right <= left) { + break; + } + + exchange(array, left, right); + } + + const pivotIndex = right; + + exchange(array, pivotIndex, startIndex); + + // 왼쪽 배열 + if (pivotIndex - 1 >= startIndex) { + quickSort(array, startIndex, pivotIndex - 1); + } + + // 오른쪽 배열 + if (pivotIndex + 1 <= endIndex) { + quickSort(array, pivotIndex + 1, endIndex); + } }; test.each([ From a9f8ee23e273308e5cfa4f2875776d898d9ec6f9 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Sat, 30 Sep 2023 22:21:09 +0900 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20problem-7=20heap=20sort=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-7/problem-7.test.js | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/problem-7/problem-7.test.js b/problem-7/problem-7.test.js index 8d36fec..8c2ac27 100644 --- a/problem-7/problem-7.test.js +++ b/problem-7/problem-7.test.js @@ -1,4 +1,87 @@ +const exchange = (array, a, b) => { + [array[b], array[a]] = [array[a], array[b]]; +}; + +const initializeHeap = (array) => { + const mid = Math.floor((array.length - 1) / 2); + + // initialize heap + for (let i = mid; i > 0; i--) { + let index = i; + + while (index <= mid) { + const leftIndex = 2 * index; + const rightIndex = 2 * index + 1; + + const current = array[index]; + const leftChild = array[leftIndex]; + const rightChild = array[rightIndex] ?? 0; + + const max = Math.max(leftChild, rightChild); + + if (current >= max) { + break; + } + + if (leftChild >= rightChild) { + exchange(array, index, leftIndex); + + index = leftIndex; + } else { + exchange(array, index, rightIndex); + + index = rightIndex; + } + } + } +}; + +const sort = (array, lastIndex) => { + if (lastIndex <= 1) { + return; + } + + const mid = Math.floor(lastIndex / 2); + + const rootIndex = 1; + + // root 교체 + exchange(array, rootIndex, lastIndex); + + // sync + let index = rootIndex; + + while (index <= mid) { + const leftIndex = 2 * index; + const rightIndex = 2 * index + 1; + + const current = array[index]; + const leftChild = leftIndex < lastIndex ? array[leftIndex] : 0; + const rightChild = rightIndex < lastIndex ? array[rightIndex] : 0; + + const max = Math.max(leftChild, rightChild); + + if (current >= max) { + break; + } + + if (leftChild >= rightChild) { + exchange(array, index, leftIndex); + + index = leftIndex; + } else { + exchange(array, index, rightIndex); + + index = rightIndex; + } + } + + sort(array, lastIndex - 1); +}; + const heapSort = (array) => { + initializeHeap(array); + sort(array, array.length - 1); }; test.each([ From 10a043ebdabaa212035229f0a40e2bcd8d4ff2a5 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Sat, 30 Sep 2023 22:26:08 +0900 Subject: [PATCH 09/10] =?UTF-8?q?feat:=20problem-7=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=EB=90=9C=20=ED=92=80=EC=9D=B4=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-7/problem-7.test.js | 95 +++++++++++-------------------------- 1 file changed, 28 insertions(+), 67 deletions(-) diff --git a/problem-7/problem-7.test.js b/problem-7/problem-7.test.js index 8c2ac27..83baac5 100644 --- a/problem-7/problem-7.test.js +++ b/problem-7/problem-7.test.js @@ -2,86 +2,47 @@ const exchange = (array, a, b) => { [array[b], array[a]] = [array[a], array[b]]; }; -const initializeHeap = (array) => { - const mid = Math.floor((array.length - 1) / 2); +const less = (a, b) => a < b; - // initialize heap - for (let i = mid; i > 0; i--) { - let index = i; +const sink = (array, i, N) => { + // 자식 노드가 있을 때까지 반복 + while (2 * i <= N) { + // 왼쪽 자식 노드부터 탐색 + let j = 2 * i; - while (index <= mid) { - const leftIndex = 2 * index; - const rightIndex = 2 * index + 1; - - const current = array[index]; - const leftChild = array[leftIndex]; - const rightChild = array[rightIndex] ?? 0; - - const max = Math.max(leftChild, rightChild); - - if (current >= max) { - break; - } + // 오른쪽 자식 노드가 더 클 경우 + if (j < N && less(array[j], array[j + 1])) { + j++; + } - if (leftChild >= rightChild) { - exchange(array, index, leftIndex); + // 더 이상 정렬할 필요가 없을 경우 + if (!less(array[i], array[j])) { + break; + } - index = leftIndex; - } else { - exchange(array, index, rightIndex); + exchange(array, i, j); - index = rightIndex; - } - } + // 자식 노드로 이동 + i = j; } }; -const sort = (array, lastIndex) => { - if (lastIndex <= 1) { - return; - } - - const mid = Math.floor(lastIndex / 2); - - const rootIndex = 1; - - // root 교체 - exchange(array, rootIndex, lastIndex); - - // sync - let index = rootIndex; - - while (index <= mid) { - const leftIndex = 2 * index; - const rightIndex = 2 * index + 1; - - const current = array[index]; - const leftChild = leftIndex < lastIndex ? array[leftIndex] : 0; - const rightChild = rightIndex < lastIndex ? array[rightIndex] : 0; - - const max = Math.max(leftChild, rightChild); +const heapSort = (array) => { + let N = array.length - 1; - if (current >= max) { - break; - } + for (let i = Math.floor(N / 2); i >= 1; i--) { + sink(array, i, N); + } - if (leftChild >= rightChild) { - exchange(array, index, leftIndex); + while (N > 1) { + // 루트 노드와 제일 마지막 노드 교환 + exchange(array, 1, N); - index = leftIndex; - } else { - exchange(array, index, rightIndex); + // 마지막 노드는 정렬되었으니 sync할 항목에서 제외 + N--; - index = rightIndex; - } + sink(array, 1, N); } - - sort(array, lastIndex - 1); -}; - -const heapSort = (array) => { - initializeHeap(array); - sort(array, array.length - 1); }; test.each([ From 9c386e73839e793cac50d475d084d07eacc38cc0 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Sun, 1 Oct 2023 21:01:26 +0900 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20problem-5=20=ED=95=98=ED=96=A5?= =?UTF-8?q?=EC=8B=9D=20=EB=A8=B8=EC=A7=80=20=EC=A0=95=EB=A0=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-5/problem-5.test.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/problem-5/problem-5.test.js b/problem-5/problem-5.test.js index 124ce9e..f72d4c8 100644 --- a/problem-5/problem-5.test.js +++ b/problem-5/problem-5.test.js @@ -1,4 +1,34 @@ -const mergeSort = (array) => { +const less = (a, b) => a < b; + +const merge = (array, start, mid, end) => { + let left = start; + let right = mid + 1; + + const temp = [...array]; + + for (let i = start; i <= end; i++) { + if (left > mid) { + array[i] = temp[right++]; + } else if (right > end) { + array[i] = temp[left++]; + } else if (less(temp[left], temp[right])) { + array[i] = temp[left++]; + } else { + array[i] = temp[right++]; + } + } +}; + +const mergeSort = (array = [], start = 0, end = array.length - 1) => { + if (start >= end) { + return; + } + + const mid = Math.floor((start + end) / 2); + + mergeSort(array, start, mid); + mergeSort(array, mid + 1, end); + merge(array, start, mid, end); }; test.each([