Skip to content
Open
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
28 changes: 28 additions & 0 deletions problem-1/sortLSD.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
const sortLSD = (words, w = words.length) => {
const N = words.length;
const R = 256;
const aux = [];

for (let d = w - 1; d >= 0; d--) {
const count = new Array(R + 1).fill(0);

// 빈도수
// words[i].charCodeAt(d) 현재 단어 위치
for (let i = 0; i < N; i++) {
count[words[i].charCodeAt(d) + 1]++;
}

// 처음 등장 인덱스
for (let i = 0; i < R; i++) {
count[i + 1] += count[i];
}

// 임시 배열 분배
for (let i = 0; i < N; i++) {
aux[count[words[i].charCodeAt(d)]++] = words[i];
}

// 원본 수정
for (let i = 0; i < N; i++) {
words[i] = aux[i];
}
}
};

test('sortLSD는 문자열을 정렬한다.', () => {
Expand Down
31 changes: 31 additions & 0 deletions problem-1/sortMSD.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,37 @@ const CUTOFF = 15;
const charAt = (s, d) => (d < s.length ? s.charCodeAt(d) : -1);

const sort = (words, aux, lo, hi, d) => {
// 정렬 범위
if (hi <= lo + CUTOFF) {
insertionSort(words, lo, hi, d);
return;
}

const count = new Array(R + 2).fill(0);

// 빈도수
for (let i = lo; i <= hi; i++) {
count[charAt(words[i], d) + 2]++;
}

// 시작 인덱스
for (let i = 0; i < R + 1; i++) {
count[i + 1] += count[i];
}

// 임시 배열 분해
for (let i = lo; i <= hi; i++) {
aux[count[charAt(words[i], d) + 1]++] = words[i];
}

// 원본 수정
for (let i = lo; i <= hi; i++) {
words[i] = aux[i - lo];
}

for (let i = 0; i < R; i++) {
sort(words, aux, lo + count[i], lo + count[i + 1] - 1, d + 1);
}
};

const sortMSD = (words) => {
Expand Down
26 changes: 26 additions & 0 deletions problem-1/sortQuickThree.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@ const exchange = (words, i, j) => {
};

const sortQuickThree = (words, lo = 0, hi = words.length - 1, d = 0) => {
if (hi <= lo) {
return;
}

const pivot = charAt(words[lo], d);

let lt = lo;
let gt = hi;
let i = lo + 1;

while (i <= gt) {
const t = charAt(words[i], d);
if (t < pivot) {
exchange(words, lt++, i++);
} else if (t > pivot) {
exchange(words, i, gt--);
} else {
i++;
}
}

sortQuickThree(words, lo, lt - 1, d);
if (pivot >= 0) {
sortQuickThree(words, lt, gt, d + 1);
}
sortQuickThree(words, gt + 1, hi, d);
};

test('sortQuickThree는 문자열을 정렬한다.', () => {
Expand Down
138 changes: 138 additions & 0 deletions problem-2/Trie.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,166 @@ class Trie {
#root = new Node();

get(key) {
return this.#get(this.#root, key, 0)?.value;
}

#get(node, key, d) {
if (!node) {
return;
}

if (d === key.length) {
return node;
}

const c = key.charCodeAt(d);
return this.#get(node.next[c], key, d + 1);
}

put(key, value) {
this.#root = this.#put(this.#root, key, value, 0);
}

#put(node, key, value, d) {
if (!node) {
node = new Node();
}

if (d === key.length) {
node.value = value;
return node;
}

const c = key.charCodeAt(d);
node.next[c] = this.#put(node.next[c], key, value, d + 1);
return node;
}

size() {
return this.#size(this.#root);
}

#size(node) {
if (node === undefined) {
return 0;
}

let count = node.value !== undefined ? 1 : 0;

for (let i = 0; i < R; i++) {
count += this.#size(node.next[i]);
}

return count;
}

keys() {
return this.keysWithPrefix('');
}

keysWithPrefix(prefix) {
const queue = [];
this.#collect(this.#get(this.#root, prefix, 0), prefix, queue);
return queue;
}

#collect(node, prefix, queue) {
if (node === undefined) {
return;
}

if (node.value !== undefined) {
queue.push(prefix);
}

for (let i = 0; i < R; i++) {
this.#collect(node.next[i], prefix + String.fromCharCode(i), queue);
}
}

keysThatMatch(pattern) {
const queue = [];
this.#collectWithPattern(this.#root, '', pattern, queue);
return queue;
}

#collectWithPattern(node, prefix, pattern, queue) {
if (node === undefined) {
return;
}

if (node === undefined) {
return;
}

if (prefix.length === pattern.length && node.value !== undefined) {
queue.push(prefix);
}

if (prefix.length === pattern.length) {
return;
}

const next = pattern[prefix.length];
for (let i = 0; i < R; i++) {
if (next === '.' || next === String.fromCharCode(i)) {
this.#collectWithPattern(
node.next[i],
prefix + String.fromCharCode(i),
pattern,
queue,
);
}
}
}

delete(key) {
this.#root = this.#delete(this.#root, key, 0);
}

#delete(node, key, d) {
if (node === undefined) {
return;
}

if (d === key.length) {
node.value = undefined;
} else {
const c = key.charCodeAt(d);
node.next[c] = this.#delete(node.next[c], key, d + 1);
}

if (node.value !== undefined) {
return node;
}

for (let i = 0; i < R; i++) {
if (node.next[i] !== undefined) {
return node;
}
}
}

longestPrefixOf(query) {
const length = this.#search(this.#root, query, 0, 0);
return query.substring(0, length);
}

#search(node, query, d, length) {
if (node === undefined) {
return length;
}

if (node.value !== undefined) {
length = d;
}

if (d === query.length) {
return length;
}

const c = query.charCodeAt(d);
return this.#search(node.next[c], query, d + 1, length);
}
}

Expand Down
17 changes: 16 additions & 1 deletion problem-3/repeat-length-encoding.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
const encode = (words) => {
const answer = [];

for (const input of words) {
answer.push(input[0] + input.length);
}

return answer.join('');
};

const decode = (string) => {
const answer = [];

for (let i = 0; i < string.length - 1; i += 2) {
const count = Number(string[i + 1]);
answer.push(string[i].repeat(count));
}

return answer;
};

test('repeat length encoding', () => {
const origin = ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaaa', 'aaaaaaaa'];
const origin = ['a', 'aa', 'aaa', 'aaaa', 'aaaaa', 'aaaaaa', 'aaaaaaa', 'aaaaaaaa'];

const encodedString = encode(origin);

Expand Down