Skip to content

Commit

Permalink
Merge pull request #460 from whewchews/main
Browse files Browse the repository at this point in the history
[pepper] Week 5 Solutions
  • Loading branch information
SamTheKorean authored Sep 16, 2024
2 parents f1b408d + 6fdca7f commit 9cc99d4
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 0 deletions.
33 changes: 33 additions & 0 deletions 3sum/whewchews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
function threeSum(nums: number[]): number[][] {
let result: [number, number, number][] = [];
const TARGET = 0;
// TC: O(NlogN)
nums.sort((a, b) => a - b);

for (let i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue;

let left = i + 1;
let right = nums.length - 1;

while (left < right) {
let sum = nums[i] + nums[left] + nums[right];

if (sum === TARGET) {
result.push([nums[i], nums[left], nums[right]]);
while (nums[left] === nums[left + 1]) left++;
while (nums[right] === nums[right - 1]) right--;
left++;
right--;
} else if (sum < TARGET) {
left++;
} else {
right--;
}
}
}

return result;
}
// TC: O(n^2)
// SC: O(n)
76 changes: 76 additions & 0 deletions best-time-to-buy-and-sell-stock/whewchews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 아이디어
* 수익을 얻기 위해서는 index보다 뒤에 오는 값 중에 현재 값보다 큰 값이 있어야 한다
* 차이가 가장 큰 두 값을 찾으면 되는데, 그 값의 순서가 작은값 다음 큰 값 순이어야 한다
* 가격의 차이를 어떻게 구할 수 있을까?
* for문을 두번 돌면서 값의 차이를 저장해둔다.(순서가 일치해야함)
* 값의 차이 중 가장 큰 값을 리턴한다.
* 리턴할 값이 없으면 0을 리턴한다.
* ====> 이 방법으로 풀었더니 타임초과가 나왔다.
* 어떻게 시간복잡도를 줄일 수 있을까?
* for문을 두번돌면 O(n^2)이 드니 for문을 한번만 돌게 하면 좋을 것 같다.
* for문을 돌면서 가장 작은 구매가, 최대 이익 두가지 변수를 업데이트 하자
* ===> 연습삼아 투포인터로도 풀어보자
*/

function maxProfit1(prices: number[]): number {
let profit = 0;

for (let i = 0; i <= prices.length - 2; i++) {
const x = prices[i];
for (let j = i + 1; j <= prices.length - 1; j++) {
const y = prices[j];
const diff = y - x;
if (x < y && profit < diff) {
profit = diff;
}
}
}

return profit;
}
// TC: O(n^2)
// SC: O(1)

function maxProfit2(prices: number[]): number {
let buyPrice = prices[0];
let profit = 0;

for (let i = 0; i <= prices.length - 1; i++) {
const todayPrice = prices[i];
const diff = todayPrice - buyPrice;

if (todayPrice <= buyPrice) {
buyPrice = todayPrice;
} else {
if (profit < diff) {
profit = todayPrice - buyPrice;
}
}
}

return profit;
}
// TC: O(n)
// SC: O(1)

function maxProfit3(prices: number[]): number {
let left = 0;
let right = 1;
let maxProfit = 0;

while (right <= prices.length - 1) {
if (prices[left] > prices[right]) {
left = right;
} else {
const profit = prices[right] - prices[left];
maxProfit = Math.max(profit, maxProfit);
}

right++;
}

return maxProfit;
}
// TC: O(n)
// SC: O(1)
45 changes: 45 additions & 0 deletions group-anagrams/whewchews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 조건
* 문자열은 영어 소문자
* 서로 anagram이 되는 쌍을 배열로 묶어서 리턴
* 자기 자신은 anagram 혼자서 가능함
* return 하는 배열 순서는 관계없음
* 아이디어
* strs를 돌면서 str에 어떤 알파벳이 몇개씩 있는지를 계산한다
* 알파벳 개수가 같은 문자열끼리 몹는다
*/
function groupAnagrams(strs: string[]): string[][] {
const anagramMap = new Map<string, string[]>();

for (const str of strs) {
const sortedStr = generateAnagramKey2(str);
if (!anagramMap.has(sortedStr)) {
anagramMap.set(sortedStr, []);
}

anagramMap.get(sortedStr)!.push(str);
}

return Array.from(anagramMap.values());
}
// TC: O(N * M)
// SC: O(N * M)

function generateAnagramKey1(str: string): string {
return str.split("").sort().join("");
}
// TC: O(NlogN)
// SC: O(N)

function generateAnagramKey2(str: string): string {
let count = new Array(26).fill(0);

for (let c of str) {
count[c.charCodeAt(0) - "a".charCodeAt(0)]++;
}

return count.join("-");
}
// TC: O(N)
// SC: O(1)
46 changes: 46 additions & 0 deletions implement-trie-prefix-tree/whewchews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 아이디어
* 삽입된 전체 word를 저장해둔다. => wordSet
* 삽입된 단어의 1글자 ~ 단어길이 글자 만큼을 전부 각각 prefix로 저장해둔다. => prefixSet
* 중복처리를 위해 Set을 사용한다.
*/
class Trie {
wordSet: Set<string>;
prefixSet: Set<string>;

constructor() {
this.wordSet = new Set();
this.prefixSet = new Set();
}

// TC: O(n) // n = word.length
// SC: O(n)
insert(word: string): void {
let result = "";
for (let i = 0; i < word.length; i++) {
result += word[i];
this.prefixSet.add(result);
}
this.wordSet.add(word);
}

// TC: O(1)
// SC: O(1)
search(word: string): boolean {
return this.wordSet.has(word);
}

// TC: O(1)
// SC: O(1)
startsWith(prefix: string): boolean {
return this.prefixSet.has(prefix);
}
}

/**
* 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)
*/
34 changes: 34 additions & 0 deletions word-break/whewchews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 조건
* 영어소문자로만 구성되어있음
* wordDict안에 있는 문자를 가지고 s를 만들 수 있으면 true return
* 아이디어
* wordDict안에 있는 단어들 중 s의 prefix 단어를 찾는다.
* prefix가 되는 단어를 뺀, 나머지 뒤의 문자열이 wordDict안에 있는 단어로 시작되는지 찾는다.
* 이 과정을 반복해서, s의 길이가 0이 되면 true를 리턴한다.
* wordDict안에 있는 단어를 다 조회해도 s가 남아있다면 false를 리턴한다.
*/

function wordBreak(s: string, wordDict: string[]): boolean {
const memo: Record<string, boolean> = {};
return isBreak(s, wordDict, memo);
}

function isBreak(s: string, wordDict: string[], memo: Record<string, boolean>) {
if (s.length === 0) return true;
if (s in memo) return memo[s];
for (const word of wordDict) {
const length = word.length;
if (s.startsWith(word) && isBreak(s.slice(length), wordDict, memo)) {
memo[s] = true;
return true;
}
}

memo[s] = false;
return false;
}
// TC: O(s*w)
// SC: O(s)
// s: s.length, w: wordDict.length

0 comments on commit 9cc99d4

Please sign in to comment.