Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[재호] WEEK 06 Solutions #462

Merged
merged 7 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions container-with-most-water/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* TC: O(H)
* SC: O(1)
* H: height.length
*/

/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function (height) {
let maximumWater = 0;
let left = 0;
let right = height.length - 1;

// 1. 투포인터를 이용하여 양끝에서 모입니다.
while (left < right) {
// 2. 최대 너비값을 갱신해주고
const h = Math.min(height[left], height[right]);
const w = right - left;

maximumWater = Math.max(maximumWater, w * h);

// 3. 왼쪽과 오른쪽 높이 중 더 낮은 쪽의 pointer를 옮깁니다.
if (height[left] < height[right]) {
left += 1;
} else {
right -= 1;
}
}

return maximumWater;
};
83 changes: 83 additions & 0 deletions design-add-and-search-words-data-structure/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
function Node() {
// 단어의 끝을 의미 + 무슨 단어인지 저장
this.value = null;
// 단어의 다음 문자로 연결되어 있는 노드맵
this.wordGraph = new Map();
}

var WordDictionary = function () {
this.wordGraph = new Map();
};

/**
* TC: O(N)
* SC: O(N)
*/

/**
* @param {string} word
* @return {void}
*/
WordDictionary.prototype.addWord = function (word) {
let pointer = this;
for (const w of word) {
if (!pointer.wordGraph.has(w)) {
pointer.wordGraph.set(w, new Node());
}
pointer = pointer.wordGraph.get(w);
}
pointer.value = word;
};

/**
* TC: O(D^W)
* SC: O(D * W)
*
* W: word.length, D: count of Dictionary.wordGraph keys
*
* 풀이: Trie 자료구조 + bfs탐색
*/

/**
* @param {string} word
* @return {boolean}
*/
WordDictionary.prototype.search = function (word) {
const queue = [{ pointer: this, index: 0 }];

// 1. BFS 탐색 방법 이용
while (queue.length > 0) {
const { pointer, index } = queue.shift();

// 2. 찾고자하는 단어의 끝에 도달했으면 해당 단어가 있는지 확인한다.
if (index === word.length) {
if (pointer.value !== null) {
return true;
}
continue;
}

if (word[index] === ".") {
// 3. 찾고자하는 단어의 문자가 '.'인 경우, 현재 graph에서 이어진 문자를 모두 탐색(queue에 추가)
for (const [key, node] of pointer.wordGraph) {
queue.push({ pointer: node, index: index + 1 });
}
} else if (pointer.wordGraph.has(word[index])) {
// 4. 찾고자하는 단어의 문자가 graph에 있는 경우 탐색(queue에 추가)
queue.push({
pointer: pointer.wordGraph.get(word[index]),
index: index + 1,
});
}
}

// 5. 더이상 탐색할 것이 없다면 해당 단어 없음으로 판단
return false;
};

/**
* Your WordDictionary object will be instantiated and called as such:
* var obj = new WordDictionary()
* obj.addWord(word)
* var param_2 = obj.search(word)
*/
30 changes: 30 additions & 0 deletions longest-increasing-subsequence/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* TC: O(N^2)
* SC: O(N)
* N: nums.length
*/

/**
* @param {number[]} nums
* @return {number}
*/
var lengthOfLIS = function (nums) {
// 각자 스스로는 최소 1의 lengthOfLIS를 가짐
const longestLength = new Array(nums.length).fill(1);
let result = 1;

// nums배열의 right까지 원소들 중 lengthOfLIS를 저장
for (let right = 1; right < nums.length; right++) {
for (let left = 0; left < right; left++) {
if (nums[left] < nums[right]) {
longestLength[right] = Math.max(
longestLength[right],
longestLength[left] + 1
);
result = Math.max(result, longestLength[right]);
}
}
}

return result;
};
140 changes: 140 additions & 0 deletions spiral-matrix/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/**
* 2차 풀이: 기존 matrix 변경 없도록 개선
*
* TC: O(ROW * COLUMN)
* matrix 전체 순회 1회
*
* SC: O(ROW * COLUMN)
* 정답 제출을 위한 result 공간복잡도
*/

/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function (matrix) {
const ROW = matrix.length;
const COLUMN = matrix[0].length;
// 1. 상하좌우 시작끝 index를 저장함
const boundary = {
top: 0,
bottom: ROW - 1,
left: 0,
right: COLUMN - 1,
};
const result = [];

while (result.length < ROW * COLUMN) {
// 2. 오른쪽으로 순회
for (let column = boundary.left; column <= boundary.right; column++) {
result.push(matrix[boundary.top][column]);
}
boundary.top += 1;

// 3. 아래로 순회
for (let row = boundary.top; row <= boundary.bottom; row++) {
result.push(matrix[row][boundary.right]);
}
boundary.right -= 1;

// 4. 모두 순회했는데 왔던길 되돌아가는 경우를 막기위해 중간 조건문 추가
if (result.length === ROW * COLUMN) {
break;
}

// 5. 왼쪽으로 순회
for (let column = boundary.right; column >= boundary.left; column--) {
result.push(matrix[boundary.bottom][column]);
}
boundary.bottom -= 1;

// 6. 위쪽으로 순회
for (let row = boundary.bottom; row >= boundary.top; row--) {
result.push(matrix[row][boundary.left]);
}
boundary.left += 1;
}

return result;
};

/**
* 1차 풀이
*
* TC: O(ROW * COLUMN)
* matrix 전체 순회 1회
*
* SC: O(ROW * COLUMN)
* 정답 제출을 위한 result 공간복잡도
*/

/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function (matrix) {
const ROW = matrix.length;
const COLUMN = matrix[0].length;
// 우하좌상 순서
const DIRECTION = [
Comment on lines +76 to +79
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 상수로 선언한 덕분에 가독성이 확 올라가는 군요. 감사합니다☺️

{
row: 0,
column: 1,
},
{
row: 1,
column: 0,
},
{
row: 0,
column: -1,
},
{
row: -1,
column: 0,
},
];

// 1. 첫 시작점 방문표시
const result = [matrix[0][0]];
matrix[0][0] = "#";

let current = {
row: 0,
column: 0,
};
let directionIndex = 0;

// 2. 총 갯수만큼 채워질때까지 순회
while (result.length < ROW * COLUMN) {
const next = {
row: current.row + DIRECTION[directionIndex].row,
column: current.column + DIRECTION[directionIndex].column,
};
// 3. 다음 순회할 곳이 유효한 좌표인지 방문한 곳인지 확인
if (
!isValidPosition(next.row, next.column) ||
matrix[next.row][next.column] === "#"
) {
// 4. 방향 전환
directionIndex = (directionIndex + 1) % 4;
} else {
// 5. 방문 표시 후 다음 좌표로 이동
result.push(matrix[next.row][next.column]);
matrix[next.row][next.column] = "#";
current = next;
}
}

return result;

function isValidPosition(row, column) {
if (row < 0 || ROW <= row) {
return false;
}
if (column < 0 || COLUMN <= column) {
return false;
}
return true;
}
};
44 changes: 44 additions & 0 deletions valid-parentheses/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* TC: O(S)
* s 매개변수의 길이만큼 순회 1번
*
* SC: O(S)
* 최악의 경우 S의 길이만큼 stack 배열에 모두 push 할 수 있기 때문에
*
* S: s.length
*/

/**
* @param {string} s
* @return {boolean}
*/
var isValid = function (s) {
const map = {
"(": ")",
"{": "}",
"[": "]",
};
const stack = [];

// 1. s의 길이만큼 순회를 하면서
for (const char of s) {
// 2. 열린 괄호라면 stack에 짝지어진 닫힌 괄호를 저장
// 3. 닫힌 괄호라면 stack에서 꺼낸 것과 동일한지 확인
switch (char) {
case "(":
case "{":
case "[":
stack.push(map[char]);
break;
case "}":
case ")":
case "]":
if (stack.pop() !== char) {
return false;
}
}
}
Comment on lines +23 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

괄호 문제에서 switch 쓸 생각은 못해봤는데 신선하네요!


// 4. 남은 괄호가 없는지 확인
return stack.length === 0;
};