Skip to content
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
68 changes: 68 additions & 0 deletions best-time-to-buy-and-sell-stock/Baekwangho.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
일단 가장 단순하게 생각했을 때,
n^2 의 시간 복잡도를 가지면 모든 경우의 수를 확인가능하다.

function maxProfit(prices: number[]): number {
let maximum = 0
for(let i=0; i<prices.length-1; i++) {
for(let j=i; j<prices.length; j++) {
if(prices[j] - prices[i] > maximum) maximum = prices[j] - prices[i]
}
}
return maximum
};
*/

/**
하지만 시간 초과가 발생하니, 다른 방법을 써보자.
이익을 구하기 위해서는 가장 낮은 지점과 가장 큰 지점에 대한 탐색이 필요하다.
가장 낮은 지점은 큰 지점보다 앞에 위치해야 한다.

만약 투 포인터로 양 끝에서 오면서 왼쪽은 가장 낮은 것, 오른쪽은 가장 높은 것을 확인해서
두 포인터가 만날 때 차분을 구한다면?

function maxProfit(prices: number[]): number {
let left = prices[0];
let right = prices[prices.length-1];
for (let i=0; i<prices.length; i++) {
if (i > (prices.length - 1 - i)) {
break
}

if (prices[i] < left) {
left = prices[i]
}

if (prices[prices.length - 1 - i] > right) {
right = prices[prices.length - 1 - i]
}
}

return left > right ? 0 : right - left
};
*/

/**
[3,2,6,5,0,3] 와 같은 경우에 일반화 되지 못한다.
정답을 기준으로, 큰 값 이후에는 그보다 큰 값이 없어야 하고,
작은 값 이전에는 그보다 작은 값이 없어야 한다.

그렇다면 포인터를 이 기준에 맞게 급격히 옮겨볼까?
...
힌트를 보고 왔다. 단순하게 최저값을 항상 갱신해주면 되는구나.
*/
function maxProfit(prices: number[]): number {
let min = 10000;
let max = 0;
for (let i = 0; i < prices.length; i++) {
if (prices[i] < min) {
min = prices[i];
continue;
}

if (prices[i] - min > max) {
max = prices[i] - min;
}
}
return max;
}
22 changes: 22 additions & 0 deletions group-anagrams/Baekwangho.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
3글자씩으로 구성된 각 문자열 배열을 순회하며, 각 문자열을 알파벳 순서로 정렬한 순서를 기준으로
동일하다면 원래의 문자열을 key 로 하는 해시에 포함시켜보자

시간 복잡도: O(n log n) 공간 복잡도: O(n) 정도 나오지 않을까?
*/
function groupAnagrams(strs: string[]): string[][] {
const anaMap = new Map<string, string[]>();

for (let i = 0; i < strs.length; i++) {
const hashKey = strs[i].split("").sort().join("");

const arr = anaMap.get(hashKey);
if (!arr) {
anaMap.set(hashKey, [strs[i]]);
} else {
anaMap.set(hashKey, [...arr, strs[i]]);
}
}

return [...anaMap.values()];
}
65 changes: 65 additions & 0 deletions implement-trie-prefix-tree/Baekwangho.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
test case 를 분석해본 결과, 결국 문자열에 대한 트리를 구성해야 하는 것으로 보임
트리는 노드로 구성할 수 있을 듯 하지만, 구현하지 않고 hash 의 연속을 만들어보는 것으로 하자.

오래걸렸지만 한번에 성공! 시간 복잡도: O(n), 공간 복잡도: O(1) 정도인 듯
*/
class Trie {
constructor(private letterHash: any = {}) {}

insert(word: string): void {
let currentHash = this.letterHash;

for (let i = 0; i < word.length; i++) {
const existHash = currentHash[word[i]];
if (existHash) {
currentHash = existHash;
} else {
currentHash[word[i]] = {};
currentHash = currentHash[word[i]];
}
}

currentHash["count"] = currentHash["count"] ? currentHash["count"] + 1 : 1;
}

search(word: string): boolean {
let currentHash = this.letterHash;

for (let i = 0; i < word.length; i++) {
const existHash = currentHash[word[i]];
// console.log(`search ${word}`, JSON.stringify(existHash), word[i])
if (existHash) {
currentHash = existHash;
} else {
return false;
}
}

return !!currentHash["count"];
}

startsWith(prefix: string): boolean {
let currentHash = this.letterHash;

for (let i = 0; i < prefix.length; i++) {
const existHash = currentHash[prefix[i]];
// console.log(`startsWith ${prefix}`, JSON.stringify(existHash), prefix[i])
if (existHash) {
currentHash = existHash;
} else {
return false;
}
}

return true;
}
}

/**
* Your Trie object will be instantiated and called as such:
* var obj = new Trie()
* obj.insert(word)
* var param_2 = obj.search(word)
* var param_3 = obj.startsWith(prefix)
*/