Skip to content

Commit

Permalink
chore: refactor two sum
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabb-c committed Apr 15, 2024
1 parent 7260957 commit 21a12ca
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 63 deletions.
2 changes: 1 addition & 1 deletion .lintstagedrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ export default {
"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [
"biome check --apply-unsafe --no-errors-on-unmatched",
],
"*.{js,ts}": "vitest related --run",
"*.ts": ["vitest related --run"],
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"license": "ISC",
"devDependencies": {
"@biomejs/biome": "^1.6.4",
"@commitlint/cli": "^19.2.1",
"@commitlint/config-conventional": "^19.1.0",
"@commitlint/cli": "^19.2.2",
"@commitlint/config-conventional": "^19.2.2",
"@types/node": "^20.12.7",
"@vitest/coverage-v8": "^1.5.0",
"@vitest/ui": "^1.5.0",
Expand Down
34 changes: 20 additions & 14 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 40 additions & 2 deletions src/arrays/1-two-sum/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { LeetcodeProblem } from "shared/typings/leetcode-problem";

/**
* Finds the indices of two numbers in an array that add up to a target sum.
* (This problem can be found on LeetCode: https://leetcode.com/problems/two-sum/)
*
* @param {number[]} nums - The array of numbers to search.
* @param {number} target - The target sum.
Expand All @@ -9,7 +10,7 @@
* @timeComplexity O(n) - Linear time complexity due to the single pass through the array.
* @spaceComplexity O(n) - Uses a Map to store seen numbers, which scales linearly with the input size.
*/
export const twoSum = (nums: number[], target: number): number[] => {
const hashMap = (nums: number[], target: number): number[] => {
// Create a Map to store numbers and their corresponding indices.
const numIndicesMap = new Map<number, number>();

Expand All @@ -30,3 +31,40 @@ export const twoSum = (nums: number[], target: number): number[] => {
// If no pair is found, return an empty array.
return [];
};

/**
* Finds the indices of two numbers in an array that add up to a target sum using brute force.
*
* @param {number[]} nums - The array of numbers to search.
* @param {number} target - The target sum.
* @returns {number[]} An array containing the indices of the two numbers that add up to the target sum, or an empty array if no such pair exists.
*
* @timeComplexity O(n^2) - Quadratic time complexity due to nested loops, where n is the length of the input array.
* @spaceComplexity O(1) - Constant space complexity as no additional data structures are used.
*/
const bruteForce = (nums: number[], target: number): number[] => {
// Iterate over each element in the array.
for (let i = 0; i < nums.length; i++) {
// Iterate over each subsequent element to form pairs.
for (let j = i + 1; j < nums.length; j++) {
// Check if the sum of the current pair equals the target.
if (nums[i] + nums[j] === target) {
// If found, return an array containing the indices of the two numbers.
return [i, j];
}
}
}

// If no pair is found, return an empty array.
return [];
};

export const leetcodeProblem: LeetcodeProblem = {
name: "1. Two Sum",
code: "1",
tags: ["Array"],
solutions: [
{ name: "HashMap", implementation: hashMap },
{ name: "Bruteforce", implementation: bruteForce },
],
};
27 changes: 13 additions & 14 deletions src/arrays/1-two-sum/tests/index.bench.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { bench, describe } from "vitest";

import type { InputTestData } from "@typings/input-data";
import { twoSum } from "..";
import { leetcodeProblem } from "..";
import { TEST_DATA } from "./test-data";

const TEST_DATA: InputTestData<{ nums: number[]; target: number }, number[]> = {
input: { nums: [2, 7, 11, 15], target: 9 },
expected: [0, 1],
};
const { name, solutions } = leetcodeProblem;

describe("Two Sum (benchmark)", () => {
const {
input: { nums, target },
} = TEST_DATA;

bench(`should find the indices of two numbers that add up to ${target}`, () => {
twoSum(nums, target);
});
describe(name, () => {
for (const { name, implementation } of solutions) {
bench(name, () => {
for (const {
input: { nums, target },
} of TEST_DATA) {
implementation(nums, target);
}
});
}
});
28 changes: 16 additions & 12 deletions src/arrays/1-two-sum/tests/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { describe, expect, it } from "vitest";

import { twoSum } from "..";
import { leetcodeProblem } from "..";
import { TEST_DATA } from "./test-data";

describe("Two Sum", () => {
for (const {
input: { nums, target },
expected,
} of TEST_DATA) {
it(`should find the indices of two numbers that add up to ${target}`, () => {
// Validate inputs
expect(nums).toBeDefined();
expect(target).toBeDefined();
// Validate output
expect(twoSum(nums, target)).toEqual(expected);
describe(leetcodeProblem.name, () => {
for (const { name, implementation } of leetcodeProblem.solutions) {
describe(name, () => {
for (const {
input: { nums, target },
expected,
} of TEST_DATA) {
it("should find the indices of two numbers that add up to target", () => {
// Validate inputs
expect(nums).toBeDefined();
expect(target).toBeDefined();
// Validate output
expect(implementation(nums, target)).toEqual(expected);
});
}
});
}
});
18 changes: 10 additions & 8 deletions src/arrays/1-two-sum/tests/test-data.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import type { InputTestData } from "@typings/input-data";
import type { InputTestData } from "shared/typings/input-data";

export const TEST_DATA: InputTestData<{ nums: number[]; target: number }, number[]>[] = [
// Basic cases within constraints:
{ input: { nums: [2, 7, 11, 15], target: 9 }, expected: [0, 1] },
{ input: { nums: [3, 2, 4], target: 6 }, expected: [1, 2] },
{ input: { nums: [5, 5], target: 10 }, expected: [0, 1] },

// Test cases at array length limits:
{ input: { nums: Array(10000).fill(1), target: 2 }, expected: [0, 1] },
{ input: { nums: [3, 2, 4, 7, 9, 11, 15], target: 26 }, expected: [5, 6] },
{ input: { nums: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], target: 19 }, expected: [8, 9] },
{
input: {
nums: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
target: 39,
},
expected: [18, 19],
},

// Test cases at element value limits:
{ input: { nums: [-1000000000, 0, 1000000000], target: 0 }, expected: [0, 2] },
Expand All @@ -16,8 +22,4 @@ export const TEST_DATA: InputTestData<{ nums: number[]; target: number }, number
// Test cases with valid solutions but near value limits:
{ input: { nums: [-999999999, 1], target: -999999998 }, expected: [0, 1] },
{ input: { nums: [999999998, 1], target: 999999999 }, expected: [0, 1] },

// Test case with no solution
{ input: { nums: [2], target: 4 }, expected: [] },
{ input: { nums: [2, 3], target: -5 }, expected: [] },
];
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { bench, describe } from "vitest";

import type { InputTestData } from "@typings/input-data";
import type { InputTestData } from "shared/typings/input-data";
import { maxProfit } from "..";

const TEST_DATA: InputTestData<number[], number> = { input: [7, 1, 5, 3, 6, 4], expected: 5 };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { InputTestData } from "@typings/input-data";
import type { InputTestData } from "shared/typings/input-data";

export const TEST_DATA: InputTestData<number[], number>[] = [
// Basic cases:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { bench, describe } from "vitest";

import type { InputTestData } from "@typings/input-data";
import type { InputTestData } from "shared/typings/input-data";
import { productExceptSelf } from "..";

const TEST_DATA: InputTestData<number[], number[]> = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { InputTestData } from "@typings/input-data";
import type { InputTestData } from "shared/typings/input-data";

/** Test data for the solution */
export const TEST_DATA: InputTestData<number[], number[]>[] = [
Expand Down
2 changes: 1 addition & 1 deletion src/arrays/54-spiral-matrix/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Matrix } from "@typings/matrix";
import type { Matrix } from "shared/typings/matrix";

/**
* Returns the elements of the input matrix in spiral order.
Expand Down
4 changes: 2 additions & 2 deletions src/arrays/54-spiral-matrix/tests/index.bench.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { bench, describe } from "vitest";

import type { InputTestData } from "@typings/input-data";
import type { Matrix } from "@typings/matrix";
import type { InputTestData } from "shared/typings/input-data";
import type { Matrix } from "shared/typings/matrix";
import { spiralOrder } from "..";

const TEST_DATA: InputTestData<Matrix<number>, number[]> = {
Expand Down
4 changes: 2 additions & 2 deletions src/arrays/54-spiral-matrix/tests/test-data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { InputTestData } from "@typings/input-data"; // Assuming you have a types file
import type { Matrix } from "@typings/matrix";
import type { InputTestData } from "shared/typings/input-data"; // Assuming you have a types file
import type { Matrix } from "shared/typings/matrix";

export const TEST_DATA: InputTestData<Matrix<number>, number[]>[] = [
{
Expand Down
File renamed without changes.
24 changes: 24 additions & 0 deletions src/shared/typings/leetcode-problem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Represents a solution to a problem, containing its name and implementation.
*/
type Solution = {
/** The name of the solution. */
name: string;
/** The implementation of the solution, which is a function taking any arguments and returning any value. */
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
implementation: (...args: any[]) => any;
};

/**
* Represents a problem on LeetCode, containing its name, code, tags, and available solutions.
*/
export type LeetcodeProblem = {
/** The name of the problem. */
name: string;
/** The code identifier of the problem on LeetCode. */
code: string;
/** An array of tags describing the problem. */
tags: string[];
/** An array of available solutions for the problem. */
solutions: Solution[];
};
File renamed without changes.
Empty file added src/shared/utils/.gitkeep
Empty file.
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"baseUrl": "./src",
// Defines path mappings for module names.
"paths": {
"@typings/*": ["typings/*"]
"@typings/*": ["shared/typings/*"],
"@utils/*": ["shared/utils/*"]
}
},
// Specifies the files to include in the compilation.
Expand Down
2 changes: 2 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export default defineConfig({
globals: true,
coverage: {
provider: "v8",
exclude: ["**/*.bench.ts", ".lintstagedrc.js", "commitlint.config.js"],
},
logHeapUsage: true,
},
});

0 comments on commit 21a12ca

Please sign in to comment.