4 |
5 |
6 | Module Pattern
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/design-patterns/module-pattern/browser/script1.js:
--------------------------------------------------------------------------------
1 | // let a = 1;
2 |
3 | let MODULE_NAMESPACE = (function iife() {
4 | let a = 1;
5 |
6 | function get() {
7 | return a
8 | }
9 |
10 | function increment() {
11 | a++
12 | }
13 |
14 | return {
15 | get,
16 | increment
17 | }
18 | }())
--------------------------------------------------------------------------------
/design-patterns/module-pattern/browser/script2.js:
--------------------------------------------------------------------------------
1 | // console.log(a)
2 |
3 | console.log(MODULE_NAMESPACE.get())
4 | console.log(MODULE_NAMESPACE.increment())
5 | console.log(MODULE_NAMESPACE.get())
--------------------------------------------------------------------------------
/design-patterns/module-pattern/node/index.js:
--------------------------------------------------------------------------------
1 | // const { get, increment } = require("./script")
2 |
3 |
4 | // console.log(get())
5 | // console.log(increment())
6 | // console.log(get())
7 |
8 |
9 | // const MODULE_NAMESPACE = require("./script")
10 |
11 | // console.log(MODULE_NAMESPACE.get())
12 | // console.log(MODULE_NAMESPACE.increment())
13 | // console.log(MODULE_NAMESPACE.get())
14 |
15 | import { get, increment } from "./script-es.mjs"
16 |
17 | console.log(get())
18 | console.log(increment())
19 | console.log(get())
--------------------------------------------------------------------------------
/design-patterns/module-pattern/node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/module-pattern/node/script-es.mjs:
--------------------------------------------------------------------------------
1 | let a = 1;
2 |
3 | export function get() {
4 | return a
5 | }
6 |
7 | export function increment() {
8 | a++
9 | }
10 |
11 | export default { get, increment }
12 |
13 |
--------------------------------------------------------------------------------
/design-patterns/module-pattern/node/script.js:
--------------------------------------------------------------------------------
1 | let a = 1;
2 |
3 | function get() {
4 | return a
5 | }
6 |
7 | function increment() {
8 | a++
9 | }
10 |
11 | module.exports = {
12 | get,
13 | increment
14 | }
--------------------------------------------------------------------------------
/design-patterns/observer-pattern/OObservable.js:
--------------------------------------------------------------------------------
1 | let observers = []
2 |
3 | let Observable = {
4 | addObserver: (observer) => {
5 | observers.push(observer)
6 | },
7 |
8 | removeObserver: (observer) => {
9 | observers.forEach((ob, i) => {
10 | if (observer === ob) {
11 | observers.splice(i, 1)
12 | }
13 | })
14 | },
15 |
16 | notifyObservers: (data) => {
17 | observers.forEach((observer) => observer(data))
18 | }
19 | }
20 |
21 | export default Observable
--------------------------------------------------------------------------------
/design-patterns/observer-pattern/Observable.js:
--------------------------------------------------------------------------------
1 | export default class Observable {
2 |
3 | constructor() {
4 | this.observers = []
5 | }
6 |
7 | addObserver(observer) {
8 | this.observers.push(observer)
9 | }
10 |
11 | removeObserver(observer) {
12 | this.observers.forEach((ob, i) => {
13 | if (observer === ob) {
14 | this.observers.splice(i, 1)
15 | }
16 | })
17 | }
18 |
19 | notifyObservers(data) {
20 | this.observers.forEach((observer) => observer(data))
21 | }
22 | }
--------------------------------------------------------------------------------
/design-patterns/observer-pattern/index.js:
--------------------------------------------------------------------------------
1 | import Observable from "./Observable.js";
2 | import OObservable from "./OObservable.js";
3 |
4 | let observable = new Observable();
5 |
6 | function observer1(data) {
7 | console.log(`Observer1: ${data}`)
8 | }
9 |
10 | function observer2(data) {
11 | console.log(`Observer2: ${data}`)
12 | }
13 |
14 | observable.addObserver(observer1)
15 | observable.addObserver(observer2)
16 |
17 | observable.notifyObservers('New Data')
18 |
19 | observable.removeObserver(observer1)
20 |
21 | observable.notifyObservers('Observer1 removed')
22 |
23 |
24 | console.log('\n')
25 |
26 | OObservable.addObserver(observer1)
27 | OObservable.addObserver(observer2)
28 |
29 | OObservable.notifyObservers('New Data')
30 |
31 | OObservable.removeObserver(observer1)
32 |
33 | OObservable.notifyObservers('Observer1 removed')
34 |
--------------------------------------------------------------------------------
/design-patterns/observer-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "observer-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/proxy-pattern/index.js:
--------------------------------------------------------------------------------
1 | let user = {
2 | name: 'Mohit',
3 | email: 'm@g.com'
4 | }
5 |
6 | let userProxy = new Proxy(user, {
7 | get(target, property) {
8 | // return target[property]
9 | return Reflect.get(target, property)
10 | },
11 | set(target, property, newValue) {
12 | // target[property] = newValue
13 | // return true
14 | if (property === 'name' && newValue.length < 3) {
15 | throw new Error('A proper name should be provided')
16 | }
17 | return Reflect.set(target, property, newValue)
18 | }
19 | })
20 |
21 | console.log(userProxy.name)
22 | userProxy.name = 'John'
23 | console.log(userProxy.name)
24 | // userProxy.name = 'Sa'
25 | userProxy.name = 'Sam'
26 | console.log(userProxy.name)
27 |
28 |
--------------------------------------------------------------------------------
/design-patterns/proxy-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "proxy-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/pub-sub-pattern/Broker.js:
--------------------------------------------------------------------------------
1 | export default class Broker {
2 | constructor() {
3 | this.subscribers = {}
4 | }
5 |
6 | subscribe(event, fn) {
7 | if (this.subscribers[event]) {
8 | this.subscribers[event] = [...this.subscribers[event], fn]
9 | } else {
10 | this.subscribers[event] = [fn]
11 | }
12 | }
13 |
14 | unsubscribe(event, fn) {
15 | if (this.subscribers[event]) {
16 | this.subscribers[event] = this.subscribers[event].filter((sub) => sub !== fn)
17 | }
18 | }
19 |
20 | publish(event, data) {
21 | this.subscribers[event].forEach(sub => sub(data));
22 | }
23 | }
--------------------------------------------------------------------------------
/design-patterns/pub-sub-pattern/Publisher.js:
--------------------------------------------------------------------------------
1 | export default class Publisher {
2 | constructor(broker) {
3 | this.broker = broker
4 | }
5 |
6 | publish(event, data) {
7 | this.broker.publish(event, data)
8 | }
9 | }
--------------------------------------------------------------------------------
/design-patterns/pub-sub-pattern/index.js:
--------------------------------------------------------------------------------
1 | import Broker from "./Broker.js";
2 | import Publisher from "./Publisher.js";
3 |
4 | function subscriber1(data) {
5 | console.log('Subscriber1 ', data)
6 | }
7 |
8 | function subscriber2(data) {
9 | console.log('Subscriber2 ', data)
10 | }
11 |
12 | let broker = new Broker()
13 | let publisher = new Publisher(broker)
14 |
15 | broker.subscribe('EVENT1', subscriber1)
16 | broker.subscribe('EVENT1', subscriber2)
17 |
18 | publisher.publish('EVENT1', 'New Data')
19 |
20 | broker.unsubscribe('EVENT1', subscriber1)
21 |
22 | publisher.publish('EVENT1', 'Subscriber 1 removed')
23 |
24 |
--------------------------------------------------------------------------------
/design-patterns/pub-sub-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pub-sub-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/singleton-pattern/DBConnection.js:
--------------------------------------------------------------------------------
1 | let instance;
2 |
3 | class DBConnection {
4 |
5 | constructor(uri) {
6 | if (instance) {
7 | throw new Error('One instance is already present')
8 | }
9 | instance = this
10 | this.uri = uri
11 | }
12 |
13 | connect() {
14 | console.log(`${this.uri} connected`)
15 | }
16 | disconnect() {
17 | console.log(`${this.uri} disconnected`)
18 | }
19 | }
20 |
21 | let dbConnection = Object.freeze(new DBConnection('some uri'))
22 | // let dbConnection = new DBConnection('some uri')
23 |
24 | export default dbConnection
--------------------------------------------------------------------------------
/design-patterns/singleton-pattern/ODBConnection.js:
--------------------------------------------------------------------------------
1 | let uri = 'some uri'
2 |
3 | let DBConnection = {
4 | connect: () => {
5 | console.log(`${uri} connected`)
6 | },
7 | disconnect: () => {
8 | console.log(`${uri} disconnected`)
9 | }
10 | }
11 |
12 | let dbConnection = Object.freeze(DBConnection)
13 |
14 | export default dbConnection
--------------------------------------------------------------------------------
/design-patterns/singleton-pattern/UpdatedDBConnection.js:
--------------------------------------------------------------------------------
1 | // For better encapsulation
2 |
3 | class DBConnection {
4 | constructor(uri) {
5 | this.uri = uri
6 | }
7 |
8 | connect() {
9 | console.log(`DB ${this.uri} has been connected`)
10 | }
11 |
12 |
13 | disconnect() {
14 | console.log(`DB ${this.uri} has been disconnected`)
15 | }
16 |
17 | static getInstance(uri) {
18 | if (!this.instance) {
19 | this.instance = new DBConnection(uri);
20 | }
21 | return this.instance;
22 | }
23 | }
24 |
25 |
26 | const singletonDBConnection = DBConnection.getInstance('some uri');
27 | Object.freeze(singletonDBConnection);
28 |
29 | export default singletonDBConnection
--------------------------------------------------------------------------------
/design-patterns/singleton-pattern/index.js:
--------------------------------------------------------------------------------
1 | import DBConnection from "./DBConnection.js";
2 | import ODBConnection from "./ODBConnection.js";
3 | import UpdatedDBConnection from "./UpdatedDBConnection.js";
4 |
5 | // DBConnection.newkey = 'value'
6 |
7 | DBConnection.connect()
8 | DBConnection.disconnect()
9 | console.log(DBConnection)
10 | console.log(DBConnection.constructor)
11 |
12 | // new DBConnection.constructor('some other uri')
13 |
14 | console.log('\n')
15 |
16 | ODBConnection.connect()
17 | ODBConnection.disconnect()
18 | console.log(ODBConnection)
19 | // console.log(ODBConnection.constructor)
20 |
21 | console.log('\n')
22 |
23 | UpdatedDBConnection.connect()
24 | UpdatedDBConnection.disconnect()
25 | console.log(UpdatedDBConnection)
26 |
27 |
--------------------------------------------------------------------------------
/design-patterns/singleton-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "singleton-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/strategy-pattern/Strategy1.js:
--------------------------------------------------------------------------------
1 | export class Strategy1 {
2 | performAction() {
3 | console.log('Strategy 1')
4 | }
5 | }
--------------------------------------------------------------------------------
/design-patterns/strategy-pattern/Strategy2.js:
--------------------------------------------------------------------------------
1 | export class Strategy2 {
2 | performAction() {
3 | console.log('Strategy 2')
4 | }
5 | }
--------------------------------------------------------------------------------
/design-patterns/strategy-pattern/StrategyManager.js:
--------------------------------------------------------------------------------
1 | export class StrategyManager {
2 | setStrategy(strategy) {
3 | this.strategy = strategy
4 | }
5 |
6 | performAction() {
7 | this.strategy.performAction()
8 | }
9 | }
--------------------------------------------------------------------------------
/design-patterns/strategy-pattern/index.js:
--------------------------------------------------------------------------------
1 | import { Strategy1 } from "./Strategy1.js";
2 | import { Strategy2 } from "./Strategy2.js";
3 | import { StrategyManager } from "./StrategyManager.js";
4 |
5 | let strategyManager = new StrategyManager()
6 |
7 | strategyManager.setStrategy(new Strategy1())
8 | strategyManager.performAction()
9 |
10 |
11 | strategyManager.setStrategy(new Strategy2())
12 | strategyManager.performAction()
--------------------------------------------------------------------------------
/design-patterns/strategy-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "strategy-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/README.md:
--------------------------------------------------------------------------------
1 | # Visitor Pattern
2 |
3 | Code for the [Youtube video](https://www.youtube.com/watch?v=7XCYhP0t9a8) on Visitor pattern in the context of AST
4 |
5 |
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/index.mjs:
--------------------------------------------------------------------------------
1 | // https://blog.bitsrc.io/what-is-an-abstract-syntax-tree-7502b71bde27
2 |
3 | // 1 * 2 + 3
4 |
5 | import BinaryExpression from "./src/BinaryExpression.mjs"
6 | import NumericLiteral from "./src/NumericLiteral.mjs"
7 | import Visitor from "./src/Visitor.mjs"
8 |
9 |
10 | const visitor = new Visitor()
11 |
12 |
13 | const oneLiteral = new NumericLiteral(1)
14 | const twoLiteral = new NumericLiteral(2)
15 | const threeLiteral = new NumericLiteral(3)
16 | // console.log("NumericLiteral", oneLiteral.accept(visitor))
17 |
18 |
19 | const leftExpression = new BinaryExpression(oneLiteral, '*', twoLiteral)
20 | const mainExpression = new BinaryExpression(leftExpression, '+', threeLiteral)
21 |
22 | // const binExpression = new BinaryExpression(oneLiteral, '+', twoLiteral)
23 | // const binExpression2 = new BinaryExpression(oneLiteral, '-', twoLiteral)
24 |
25 |
26 | // console.log("ADD", binExpression.accept(visitor))
27 | // console.log("SUBTRACT", binExpression2.accept(visitor))
28 | // console.log("MULTIPLY", binExpression3.accept(visitor))
29 |
30 | console.log(mainExpression)
31 | console.log(mainExpression.accept(visitor))
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "visitor-pattern",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC"
12 | }
13 |
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/src/BinaryExpression.mjs:
--------------------------------------------------------------------------------
1 | export default class BinaryExpression {
2 | constructor(left, operator, right) {
3 | this.left = left
4 | this.operator = operator
5 | this.right = right
6 | }
7 |
8 | accept(visitor) {
9 | return visitor.visitBinaryExpression(this)
10 | }
11 | }
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/src/NumericLiteral.mjs:
--------------------------------------------------------------------------------
1 | export default class NumericLiteral {
2 | constructor(value) {
3 | this.value = value
4 | }
5 |
6 | accept(visitor) {
7 | return visitor.visitNumericLiteral(this)
8 | }
9 | }
--------------------------------------------------------------------------------
/design-patterns/visitor-pattern/src/Visitor.mjs:
--------------------------------------------------------------------------------
1 | export default class Visitor {
2 |
3 | visitBinaryExpression(binExpr) {
4 | switch (binExpr.operator) {
5 | case "+":
6 | return binExpr.left.accept(this) + binExpr.right.accept(this)
7 | case "-":
8 | return binExpr.left.accept(this) - binExpr.right.accept(this)
9 | case "*":
10 | return binExpr.left.accept(this) * binExpr.right.accept(this)
11 |
12 | }
13 | }
14 |
15 | visitNumericLiteral(litExpr) {
16 | return litExpr.value
17 | }
18 | }
--------------------------------------------------------------------------------
/dsa-questions/leetcode/best-time-to-buy-and-sell-stock-ii/best-time-to-buy-and-sell-stock-ii.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
3 | */
4 |
5 | // Time Complexity: O(N), where N is the length of the prices array. We only make one pass through the array.
6 | // Space Complexity: O(1). We only use a few extra variables.
7 |
8 | /**
9 | * @param {number[]} prices
10 | * @return {number}
11 | */
12 | var maxProfit = function (prices) {
13 | let totalProfit = 0;
14 |
15 | // Iterate through the array
16 | for (let day = 1; day < prices.length; day++) {
17 | // If the price today is higher than the price yesterday
18 | if (prices[day] > prices[day - 1]) {
19 | // Add the profit to the total profit
20 | totalProfit += prices[day] - prices[day - 1];
21 | }
22 | }
23 |
24 | return totalProfit;
25 | };
26 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/climbing-stairs/climbing-stairs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/climbing-stairs/
3 | */
4 |
5 | // Time Complexity: O(2^N) - Exponential time complexity (inefficient for large N)
6 | // This approach leads to Time Limit Exceeded (TLE) for larger inputs.
7 |
8 | /**
9 | * @param {number} n - The number of steps to reach the top
10 | * @return {number} - The number of distinct ways to climb to the top
11 | */
12 | var climbStairs = function (n) {
13 | // Base case: If there are 0 or 1 steps, there's only 1 way to reach the top
14 | if (n === 0 || n === 1) return 1;
15 |
16 | // Recursively calculate the number of ways to climb when taking 1 step or 2 steps
17 | let climbOneStep = climbStairs(n - 1);
18 | let climbTwoSteps = climbStairs(n - 2);
19 |
20 | // The total number of ways to reach the top is the sum of the two possibilities
21 | return climbOneStep + climbTwoSteps;
22 | };
23 |
24 | // Optimized solution using memoization to reduce time complexity from O(2^N) to O(N)
25 | let map = new Map(); // Map to store already calculated results for subproblems
26 |
27 | /**
28 | * @param {number} n - The number of steps to reach the top
29 | * @return {number} - The number of distinct ways to climb to the top
30 | */
31 | var climbStairs = function (n) {
32 | // Base case: If there are 0 or 1 steps, there's only 1 way to reach the top
33 | if (n === 0 || n === 1) return 1;
34 |
35 | // If the result for the current number of steps is already calculated, return it
36 | if (map.has(n)) {
37 | return map.get(n);
38 | }
39 |
40 | // Recursively calculate the number of ways to climb when taking 1 step or 2 steps
41 | let climbOneStep = climbStairs(n - 1);
42 | let climbTwoSteps = climbStairs(n - 2);
43 | let totalWays = climbOneStep + climbTwoSteps;
44 |
45 | // Store the result in the map to avoid redundant calculations in future calls
46 | map.set(n, totalWays);
47 |
48 | // Return the total number of ways to reach the top
49 | return totalWays;
50 | };
51 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/combination-sum/combination-sum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/combination-sum/
3 | */
4 |
5 | // TODO need to check more accurate TC
6 | // TC O(2^N * N)
7 | // Picking and not picking will make 2^N and copying for the base case would make N
8 |
9 | /**
10 | * @param {number[]} candidates - The array of candidate numbers
11 | * @param {number} target - The target sum we need to achieve
12 | * @return {number[][]} - A list of all unique combinations that sum up to the target
13 | */
14 | var combinationSum = function (candidates, target) {
15 | const ans = []; // Store all the valid combinations here
16 | helper(candidates, target, 0, [], ans); // Start the recursive process
17 | return ans;
18 | };
19 |
20 | /**
21 | * Recursive helper function to generate combinations
22 | *
23 | * @param {number[]} candidates - The input array of numbers
24 | * @param {number} target - The remaining sum we need to achieve
25 | * @param {number} index - The current index in the array we're considering
26 | * @param {number[]} combinationsFormedSoFar - The current combination being formed
27 | * @param {number[][]} ans - The final array to store all valid combinations
28 | */
29 | function helper(candidates, target, index, combinationsFormedSoFar, ans) {
30 | // Base case: If the remaining target is 0, we've found a valid combination
31 | if (target === 0) {
32 | ans.push([...combinationsFormedSoFar]); // Add a copy of the current combination to ans
33 | return;
34 | }
35 |
36 | // If the remaining target is negative or we've exhausted all candidates, stop the recursion
37 | if (target < 0 || index === candidates.length) {
38 | return;
39 | }
40 |
41 | // Recursive case 1: Do not pick the current candidate
42 | helper(candidates, target, index + 1, combinationsFormedSoFar, ans);
43 |
44 | // Recursive case 2: Pick the current candidate and continue
45 | combinationsFormedSoFar.push(candidates[index]); // Add the current candidate to the combination
46 | helper(
47 | candidates,
48 | target - candidates[index], // Reduce the target by the current candidate's value
49 | index, // Stay at the current index to allow repeated use of the same candidate
50 | combinationsFormedSoFar,
51 | ans
52 | );
53 |
54 | // Backtrack by removing the last element to restore the previous state
55 | combinationsFormedSoFar.pop();
56 | }
57 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/contains-duplicate/contains-duplicate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/contains-duplicate/
3 | */
4 |
5 | // Time Complexity: O(N log N), where N is the number of elements in the array. This is due to the sorting operation, which dominates the complexity. The iteration through the array is O(N), but sorting is the most time-consuming operation here.
6 | // Space Complexity: O(1), assuming the sorting is done in-place.
7 |
8 | /**
9 | * Checks if there are any duplicate values in the given array.
10 | *
11 | * @param {number[]} nums - The input array of integers.
12 | * @return {boolean} - Returns true if there are duplicates, false otherwise.
13 | */
14 | var containsDuplicate = function (nums) {
15 | // Sort the array to bring duplicate elements next to each other
16 | nums.sort((a, b) => a - b);
17 |
18 | // Iterate through the sorted array
19 | for (let index = 1; index < nums.length; index++) {
20 | // Check if the current value is the same as the previous value
21 | const currentValue = nums[index];
22 | if (currentValue === nums[index - 1]) {
23 | // If duplicate is found, return true
24 | return true;
25 | }
26 | }
27 |
28 | // If no duplicates are found, return false
29 | return false;
30 | };
31 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/delete-node-in-a-linked-list/delete-node-in-a-linked-list.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/delete-node-in-a-linked-list/
3 | */
4 |
5 | // Time Complexity: O(1)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val) {
9 | * this.val = val;
10 | * this.next = null;
11 | * }
12 | */
13 | /**
14 | * @param {ListNode} node
15 | * @return {void} Do not return anything, modify node in-place instead.
16 | */
17 | var deleteNode = function (node) {
18 | // Copy the value of the next node to the current node
19 | node.val = node.next.val;
20 |
21 | // Skip over the next node
22 | node.next = node.next.next;
23 | };
24 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/first-unique-character-in-a-string/first-unique-character-in-a-string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/first-unique-character-in-a-string/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | // Space Complexity: O(1) (constant space) in terms of the alphabet since we're only dealing with lowercase English letters (a fixed set of 26 characters).
7 |
8 | /**
9 | * @param {string} s
10 | * @return {number}
11 | */
12 | var firstUniqChar = function (s) {
13 | let charMap = new Map();
14 |
15 | for (let char of s) {
16 | charMap.set(char, (charMap.get(char) ?? 0) + 1);
17 | }
18 |
19 | for (let index = 0; index < s.length; index++) {
20 | if (charMap.get(s[index]) === 1) {
21 | return index;
22 | }
23 | }
24 |
25 | return -1;
26 | };
27 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/linked-list-cycle/linked-list-cycle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/linked-list-cycle/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val) {
9 | * this.val = val;
10 | * this.next = null;
11 | * }
12 | */
13 |
14 | /**
15 | * @param {ListNode} head
16 | * @return {boolean}
17 | */
18 | var hasCycle = function (head) {
19 | let slow = head,
20 | fast = head;
21 |
22 | while (fast && fast.next) {
23 | slow = slow.next;
24 | fast = fast.next.next;
25 | if (slow === fast) {
26 | return true;
27 | }
28 | }
29 |
30 | return false;
31 | };
32 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/matrix-diagonal-sum/matrix-diagonal-sum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/matrix-diagonal-sum/
3 | */
4 |
5 | // TC - O(N)
6 | /**
7 | * The function calculates the sum of the primary and secondary diagonals of a square matrix.
8 | * The primary diagonal runs from the top-left to the bottom-right.
9 | * The secondary diagonal runs from the top-right to the bottom-left.
10 | * If the matrix has an odd number of rows, the center element (which appears in both diagonals) is only counted once.
11 | *
12 | * @param {number[][]} mat - The input square matrix.
13 | * @return {number} - The sum of the diagonals.
14 | */
15 | var diagonalSum = function (mat) {
16 | let r = mat.length; // Number of rows
17 | let c = mat[0].length; // Number of columns
18 |
19 | let sum = 0;
20 | for (let rowIndex = 0; rowIndex < r; rowIndex++) {
21 | // Get the primary diagonal element
22 | let primaryDiagonalElement = mat[rowIndex][rowIndex];
23 | sum += primaryDiagonalElement;
24 |
25 | // Get the secondary diagonal element
26 | let lastRowElement = c - 1;
27 | let secondaryDiagonalElement = mat[rowIndex][lastRowElement - rowIndex];
28 |
29 | // If the element is not the same as the primary diagonal element, add it
30 | if (rowIndex !== lastRowElement - rowIndex) {
31 | sum += secondaryDiagonalElement;
32 | }
33 | }
34 |
35 | return sum;
36 | };
37 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/maximum-depth-of-binary-tree/maximum-depth-of-binary-tree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/maximum-depth-of-binary-tree/
3 | */
4 |
5 | /*
6 | Time Complexity: O(n), where n is the number of nodes in the binary tree. Each node is visited exactly once.
7 | Space Complexity: O(h), where h is the height of the binary tree. This space is used by the recursion stack. In the worst case (if the tree is completely unbalanced), this could be O(n).
8 | */
9 | /**
10 | * Definition for a binary tree node.
11 | * function TreeNode(val, left, right) {
12 | * this.val = (val===undefined ? 0 : val);
13 | * this.left = (left===undefined ? null : left);
14 | * this.right = (right===undefined ? null : right);
15 | * }
16 | */
17 |
18 | /**
19 | * @param {TreeNode} root
20 | * @return {number}
21 | */
22 | var maxDepth = function (root) {
23 | // Base case: if the root is null, return 0
24 | if (root === null) {
25 | return 0;
26 | }
27 |
28 | // Recursively find the depth of the left and right subtrees
29 | let leftDepth = maxDepth(root.left);
30 | let rightDepth = maxDepth(root.right);
31 |
32 | // The maximum depth is 1 + the maximum of the left and right depths
33 | return 1 + Math.max(leftDepth, rightDepth);
34 | };
35 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/merge-two-sorted-lists/merge-two-sorted-lists.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/merge-two-sorted-lists/
3 | */
4 |
5 | // TC O(n + m)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val, next) {
9 | * this.val = (val===undefined ? 0 : val)
10 | * this.next = (next===undefined ? null : next)
11 | * }
12 | */
13 | /**
14 | * @param {ListNode} list1
15 | * @param {ListNode} list2
16 | * @return {ListNode}
17 | */
18 | var mergeTwoLists = function (list1, list2) {
19 | // Create a dummy node to serve as the start of the merged list
20 | let dummyHead = new ListNode();
21 | let current = dummyHead;
22 |
23 | // Traverse both lists
24 | while (list1 !== null && list2 !== null) {
25 | if (list1.val <= list2.val) {
26 | // If list1's node value is smaller or equal, append it to the merged list
27 | current.next = list1;
28 | list1 = list1.next; // Move to the next node in list1
29 | } else {
30 | // If list2's node value is smaller, append it to the merged list
31 | current.next = list2;
32 | list2 = list2.next; // Move to the next node in list2
33 | }
34 | current = current.next; // Move to the next node in the merged list
35 | }
36 |
37 | // If one of the lists is exhausted, append the remaining part of the other list
38 | if (list1 !== null) {
39 | current.next = list1;
40 | } else {
41 | current.next = list2;
42 | }
43 |
44 | // The merged list starts from the next node of the dummy node
45 | return dummyHead.next;
46 | };
47 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/move-zeroes/move-zeroes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/move-zeroes/
3 | */
4 |
5 | // Time Complexity: O(n), where n is the length of the array. Each element is processed once
6 | /**
7 | * Moves all zeros in the array to the end while maintaining the relative order of non-zero elements.
8 | *
9 | * @param {number[]} nums - The input array of integers.
10 | * @return {void} - The function modifies the array in place and does not return anything.
11 | */
12 | var moveZeroes = function (nums) {
13 | let lastNonZeroIndex = 0; // Pointer for the position of the next non-zero element
14 |
15 | // Iterate through the array
16 | let i = 0;
17 | while (i < nums.length) {
18 | if (nums[i] !== 0) {
19 | // Swap the current non-zero element with the element at lastNonZeroIndex
20 | [nums[i], nums[lastNonZeroIndex]] = [nums[lastNonZeroIndex], nums[i]];
21 | lastNonZeroIndex++;
22 | }
23 | i++;
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/palindrome-linked-list/palindrome-linked-list.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/palindrome-linked-list/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val, next) {
9 | * this.val = (val===undefined ? 0 : val)
10 | * this.next = (next===undefined ? null : next)
11 | * }
12 | */
13 |
14 | /**
15 | * @param {ListNode} head
16 | * @return {boolean}
17 | */
18 | var isPalindrome = function (head) {
19 | if (!head || !head.next) return true; // A list with 0 or 1 node is a palindrome
20 |
21 | // Step 1: Find the middle of the linked list
22 | let slow = head,
23 | fast = head;
24 | while (fast && fast.next) {
25 | slow = slow.next;
26 | fast = fast.next.next;
27 | }
28 |
29 | // Step 2: Reverse the second half of the linked list
30 | let prev = null;
31 | while (slow) {
32 | let nextNode = slow.next;
33 | slow.next = prev;
34 | prev = slow;
35 | slow = nextNode;
36 | }
37 |
38 | // Step 3: Compare the first half and the reversed second half
39 | let left = head,
40 | right = prev;
41 | while (right) {
42 | // We only need to compare up to the end of the reversed second half
43 | if (left.val !== right.val) return false;
44 | left = left.next;
45 | right = right.next;
46 | }
47 |
48 | // Step 4 (Optional): Restore the original order of the second half (if needed)
49 | // -- This step is not necessary unless we need to keep the list intact.
50 |
51 | return true;
52 | };
53 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/plus-one/plus-one.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/plus-one/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | /**
7 | * @param {number[]} digits
8 | * @return {number[]}
9 | */
10 | var plusOne = function (digits) {
11 | // Traverse the digits array from the end (least significant digit) to the beginning
12 | for (let i = digits.length - 1; i >= 0; i--) {
13 | // Check if the current digit is less than 9
14 | if (digits[i] < 9) {
15 | // If it is less than 9, simply increment this digit by one
16 | digits[i]++;
17 | // Return the updated digits array as no further carry is needed
18 | return digits;
19 | }
20 |
21 | // If the current digit is 9, setting it to 0 since 9 + 1 will generate a carry
22 | digits[i] = 0;
23 | }
24 |
25 | // After the loop, if all digits were 9 (e.g., [9, 9, 9]), all have been set to 0.
26 | // We need to add a new most significant digit to handle the carry (e.g., [1, 0, 0, 0])
27 | // This step creates a new array with 1 followed by all zeroes.
28 | return [1, ...digits];
29 | };
30 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/remove-duplicates-from-sorted-array/remove-duplicates-from-sorted-array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/remove-duplicates-from-sorted-array/
3 | */
4 |
5 | // Time Complexity: O(N)
6 | // Space Complexity: O(1)
7 | /**
8 | * @param {number[]} nums
9 | * @return {number}
10 | */
11 | var removeDuplicates = function (nums) {
12 | if (nums.length === 0) return 0;
13 |
14 | let uniqueIndex = 0; // Pointer for the unique element's position
15 |
16 | // Iterate through the array
17 | for (let currentIndex = 1; currentIndex < nums.length; currentIndex++) {
18 | // If a new unique element is found
19 | if (nums[currentIndex] !== nums[uniqueIndex]) {
20 | uniqueIndex++;
21 | nums[uniqueIndex] = nums[currentIndex]; // Place the unique element at the uniqueIndex-th position
22 | }
23 | }
24 |
25 | // Return the count of unique elements
26 | return uniqueIndex + 1;
27 | };
28 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/remove-nth-node-from-end-of-list/remove-nth-node-from-end-of-list.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/remove-nth-node-from-end-of-list/
3 | */
4 |
5 | // TC O(n)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val, next) {
9 | * this.val = (val===undefined ? 0 : val)
10 | * this.next = (next===undefined ? null : next)
11 | * }
12 | */
13 | /**
14 | * Removes the nth node from the end of the list.
15 | *
16 | * @param {ListNode} head - The head of the linked list.
17 | * @param {number} n - The position from the end of the list to remove the node.
18 | * @return {ListNode} - The head of the modified list.
19 | */
20 | var removeNthFromEnd = function (head, n) {
21 | // Create a dummy node that points to the head of the list.
22 | // This helps in handling edge cases, such as removing the head itself.
23 | let dummyHead = new ListNode();
24 | dummyHead.next = head;
25 |
26 | // Initialize two pointers, both starting from the dummy node.
27 | let slow = dummyHead;
28 | let fast = dummyHead;
29 |
30 | // Move the fast pointer n+1 steps ahead to maintain the gap between fast and slow.
31 | while (n >= 0) {
32 | fast = fast.next;
33 | n--;
34 | }
35 |
36 | // Move both pointers until fast reaches the end of the list.
37 | while (fast != null) {
38 | fast = fast.next;
39 | slow = slow.next;
40 | }
41 |
42 | // Now, slow.next is the node to be removed.
43 | // Skip the node to remove it from the list.
44 | slow.next = slow.next.next;
45 |
46 | // Return the head of the modified list.
47 | return dummyHead.next;
48 | };
49 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/reverse-linked-list/reverse-linked-list.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/reverse-linked-list/
3 | */
4 |
5 | // TC O(N)
6 | /**
7 | * Definition for singly-linked list.
8 | * function ListNode(val, next) {
9 | * this.val = (val===undefined ? 0 : val)
10 | * this.next = (next===undefined ? null : next)
11 | * }
12 | */
13 | /**
14 | * @param {ListNode} head
15 | * @return {ListNode}
16 | */
17 | var reverseList = function (head) {
18 | // Initialize previous as null and current as the head of the list
19 | let prev = null;
20 | let curr = head;
21 |
22 | // Traverse the list
23 | while (curr !== null) {
24 | // Temporarily store the next node
25 | let nextNode = curr.next;
26 |
27 | // Reverse the current node's pointer
28 | curr.next = prev;
29 |
30 | // Move prev and curr one step forward
31 | prev = curr;
32 | curr = nextNode;
33 | }
34 |
35 | // After the loop, prev will be pointing to the new head of the reversed list
36 | return prev;
37 | };
38 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/reverse-string/reverse-string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/reverse-string/
3 | */
4 |
5 | // Time Complexity: O(n)
6 |
7 | /**
8 | * @param {character[]} s
9 | * @return {void} Do not return anything, modify s in-place instead.
10 | */
11 | var reverseString = function (s) {
12 | let start = 0;
13 | let end = s.length - 1;
14 |
15 | while (start < end) {
16 | [s[start], s[end]] = [s[end], s[start]];
17 | start++;
18 | end--;
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/rotate-array/rotate-array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/rotate-array/
3 | */
4 |
5 | // Time Complexity: O(N), where N is the length of the array. Each element is reversed a constant number of times.
6 | // Space Complexity: O(1). The algorithm uses a constant amount of extra space.
7 |
8 | /**
9 | * Rotate the array to the right by k steps.
10 | *
11 | * @param {number[]} nums - The array to rotate.
12 | * @param {number} k - The number of steps to rotate the array.
13 | * @return {void} - The function modifies the array in place.
14 | */
15 | var rotate = function (nums, k) {
16 | const n = nums.length;
17 | k = k % n; // In case k is greater than the length of the array
18 |
19 | // Reverse the entire array
20 | reverse(nums, 0, n - 1);
21 | // Reverse the first k elements
22 | reverse(nums, 0, k - 1);
23 | // Reverse the remaining elements
24 | reverse(nums, k, n - 1);
25 | };
26 |
27 | /**
28 | * Helper function to reverse a portion of the array.
29 | *
30 | * @param {number[]} array - The array to reverse.
31 | * @param {number} start - The start index of the portion to reverse.
32 | * @param {number} end - The end index of the portion to reverse.
33 | */
34 | function reverse(array, start, end) {
35 | while (start < end) {
36 | [array[start], array[end]] = [array[end], array[start]];
37 | start++;
38 | end--;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/rotate-image/rotate-image.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/rotate-image/
3 | */
4 |
5 | // Time Complexity: O(n^2)
6 | // Space Complexity: O(1)
7 | /**
8 | * Rotates the input matrix by 90 degrees clockwise in-place.
9 | * The approach involves two steps:
10 | * 1. Transpose the matrix.
11 | * 2. Reverse each row to achieve the desired rotation.
12 | *
13 | * @param {number[][]} matrix - 2D array representing the matrix to be rotated.
14 | * @return {void} Do not return anything, modify matrix in-place instead.
15 | */
16 | var rotate = function (matrix) {
17 | // Step 1: Transpose the matrix
18 | // In a transpose, we convert rows into columns.
19 | // We swap the elements at (rowIndex, colIndex) with (colIndex, rowIndex).
20 | for (let rowIndex = 0; rowIndex < matrix.length; rowIndex++) {
21 | // Notice that the inner loop runs only for colIndex < rowIndex
22 | // to avoid unnecessary swaps and to handle only one side of the diagonal.
23 | for (let colIndex = 0; colIndex < rowIndex; colIndex++) {
24 | // Swap elements across the diagonal
25 | [matrix[rowIndex][colIndex], matrix[colIndex][rowIndex]] = [
26 | matrix[colIndex][rowIndex],
27 | matrix[rowIndex][colIndex],
28 | ];
29 | }
30 | }
31 |
32 | // Step 2: Reverse each row
33 | // After transposing, reverse each row to achieve the 90-degree rotation.
34 | for (let rowIndex = 0; rowIndex < matrix.length; rowIndex++) {
35 | matrix[rowIndex].reverse();
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/single-number/single-number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/single-number/
3 | */
4 |
5 | // Time Complexity: O(N), where N is the number of elements in the array. We are iterating through the array once.
6 | // Space Complexity: O(1), since we are using only a constant amount of extra space
7 | /**
8 | * Finds the single number in the array where every other number appears twice.
9 | *
10 | * @param {number[]} nums - The input array of integers.
11 | * @return {number} - The single number that does not have a duplicate.
12 | */
13 | var singleNumber = function (nums) {
14 | // Initialize the result variable
15 | let result = 0;
16 |
17 | // Iterate through the array
18 | for (let num of nums) {
19 | // Apply XOR operation
20 | result ^= num;
21 | }
22 |
23 | // Return the single number
24 | return result;
25 | };
26 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/subsets/subsets.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/subsets/
3 | */
4 |
5 | // TC O(2^N * N)
6 | // Picking and not picking will make 2^N and copying for the base case would make N
7 |
8 | /**
9 | * @param {number[]} nums
10 | * @return {number[][]}
11 | */
12 | var subsets = function (nums) {
13 | const ans = []; // Store all the subsets here
14 | helper(nums, 0, [], ans); // Start the recursive process
15 | return ans;
16 | };
17 |
18 | /**
19 | * Recursive helper function to generate subsets
20 | *
21 | * @param {number[]} nums - The input array of numbers
22 | * @param {number} index - The current index in the array we're considering
23 | * @param {number[]} combinationsFormedSoFar - The current subset being formed
24 | * @param {number[][]} ans - The final array to store all subsets
25 | */
26 | function helper(nums, index, combinationsFormedSoFar, ans) {
27 | // Base case: If we've considered all elements
28 | if (index === nums.length) {
29 | // Note: In JavaScript, arrays are passed by reference
30 | ans.push([...combinationsFormedSoFar]); // Add a copy of the current subset to ans
31 | return;
32 | }
33 |
34 | // Recursive case 1: Do not pick the current element
35 | helper(nums, index + 1, combinationsFormedSoFar, ans);
36 |
37 | // Recursive case 2: Pick the current element
38 | combinationsFormedSoFar.push(nums[index]); // Add the current element to the subset
39 | helper(nums, index + 1, combinationsFormedSoFar, ans);
40 |
41 | // Backtrack by removing the last element to restore the previous state
42 | combinationsFormedSoFar.pop();
43 | }
44 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/symmetric-tree/symmetric-tree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/symmetric-tree/
3 | */
4 |
5 | /*
6 | Time Complexity is O(n), where n is the number of nodes in the binary tree.
7 | Space Complexity is O(h), where h is the height of the binary tree
8 | */
9 |
10 | /**
11 | * Definition for a binary tree node.
12 | * function TreeNode(val, left, right) {
13 | * this.val = (val===undefined ? 0 : val)
14 | * this.left = (left===undefined ? null : left)
15 | * this.right = (right===undefined ? null : right)
16 | * }
17 | */
18 | /**
19 | * @param {TreeNode} root
20 | * @return {boolean}
21 | */
22 | var isSymmetric = function (root) {
23 | return isMirror(root, root);
24 | };
25 |
26 | /**
27 | * Helper function to determine if two trees are mirror images of each other.
28 | *
29 | * @param {TreeNode} tree1 - The root node of the first tree.
30 | * @param {TreeNode} tree2 - The root node of the second tree.
31 | * @return {boolean} - Returns true if the trees are mirrors of each other, otherwise false.
32 | */
33 | function isMirror(tree1, tree2) {
34 | // Both trees are empty, thus they are symmetric
35 | if (tree1 === null && tree2 === null) {
36 | return true;
37 | }
38 |
39 | // One tree is empty while the other is not, thus they are not symmetric
40 | if (tree1 === null || tree2 === null) {
41 | return false;
42 | }
43 |
44 | // The root values are different, thus they are not symmetric
45 | if (tree1.val !== tree2.val) {
46 | return false;
47 | }
48 |
49 | // Recursively check if the left subtree of tree1 is a mirror of the right subtree of tree2
50 | // and if the right subtree of tree1 is a mirror of the left subtree of tree2
51 | return isMirror(tree1.left, tree2.right) && isMirror(tree1.right, tree2.left);
52 | }
53 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/transpose-matrix/transpose-matrix.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/transpose-matrix/
3 | */
4 |
5 | // TC - O(M*N)
6 | /**
7 | * Given a 2D matrix, this function returns its transpose.
8 | * The transpose of a matrix is obtained by swapping its rows and columns.
9 | *
10 | * @param {number[][]} matrix - The input 2D matrix.
11 | * @return {number[][]} - The transposed matrix.
12 | */
13 | var transpose = function (matrix) {
14 | // Get the number of rows and columns in the original matrix
15 | let r = matrix.length;
16 | let c = matrix[0].length;
17 |
18 | // Create an empty output matrix with the dimensions swapped (rows become columns, columns become rows)
19 | let output = Array.from({ length: c }, () => Array(r).fill(0));
20 |
21 | // Iterate through each element of the original matrix
22 | for (let rowIndex = 0; rowIndex < r; rowIndex++) {
23 | for (let colIndex = 0; colIndex < c; colIndex++) {
24 | // Assign the value at [rowIndex][colIndex] in the original matrix to [colIndex][rowIndex] in the output matrix
25 | output[colIndex][rowIndex] = matrix[rowIndex][colIndex];
26 | }
27 | }
28 |
29 | // Return the transposed matrix
30 | return output;
31 | };
32 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/two-sum/two-sum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/two-sum/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | // Space Complexity: O(n)
7 | /**
8 | * Find two indices in the array such that their values add up to the target.
9 | *
10 | * @param {number[]} nums - Array of integers.
11 | * @param {number} target - The target sum.
12 | * @return {number[]} - The indices of the two numbers that add up to the target.
13 | */
14 | var twoSum = function (nums, target) {
15 | // Create a Map to store numbers and their indices
16 | const numToIndex = new Map();
17 |
18 | // Iterate over each number in the array
19 | for (let i = 0; i < nums.length; i++) {
20 | const currentNum = nums[i];
21 | const complement = target - currentNum;
22 |
23 | // Check if the complement (target - currentNum) exists in the Map
24 | if (numToIndex.has(complement)) {
25 | // If it exists, return the indices of the complement and the current number
26 | return [numToIndex.get(complement), i];
27 | }
28 |
29 | // If the complement does not exist in the Map, store the current number and its index
30 | numToIndex.set(currentNum, i);
31 | }
32 |
33 | // If no solution is found, return an empty array (should not be reached with valid input)
34 | return [];
35 | };
36 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/valid-anagram/valid-anagram.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/valid-anagram/
3 | */
4 |
5 | // Time Complexity: O(n)
6 | /**
7 | * Determines if two strings are anagrams of each other.
8 | *
9 | * @param {string} s - The first string.
10 | * @param {string} t - The second string.
11 | * @return {boolean} - Returns true if the strings are anagrams, otherwise false.
12 | */
13 | var isAnagram = function (s, t) {
14 | // If the lengths are different, they cannot be anagrams
15 | if (s.length !== t.length) {
16 | return false;
17 | }
18 |
19 | // Initialize an array to count character frequencies (for 26 lowercase English letters)
20 | const charCount = new Array(26).fill(0);
21 |
22 | // Increment the count for each character in the first string
23 | for (let i = 0; i < s.length; i++) {
24 | charCount[s.charCodeAt(i) - 97]++;
25 | }
26 |
27 | // Decrement the count for each character in the second string
28 | for (let i = 0; i < t.length; i++) {
29 | charCount[t.charCodeAt(i) - 97]--;
30 | }
31 |
32 | // If any count is not zero, the strings are not anagrams
33 | for (let count of charCount) {
34 | if (count !== 0) {
35 | return false;
36 | }
37 | }
38 |
39 | // If all counts are zero, the strings are anagrams
40 | return true;
41 | };
42 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/valid-palindrome/valid-palindrome.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/valid-palindrome/
3 | */
4 |
5 | // Time Complexity: O(n): The string is processed twice (once for filtering and once for palindrome checking), where n is the length of the string.
6 | // Space Complexity: O(n): The filtered string is stored in a new variable.
7 | /**
8 | * @param {string} s
9 | * @return {boolean}
10 | */
11 | var isPalindrome = function (s) {
12 | let cleanedS = s.toLowerCase().replace(/[^a-z0-9]/g, "");
13 |
14 | let left = 0;
15 | let right = cleanedS.length - 1;
16 |
17 | while (left < right) {
18 | if (cleanedS[left] !== cleanedS[right]) {
19 | return false;
20 | }
21 | left++;
22 | right--;
23 | }
24 |
25 | return true;
26 | };
27 |
--------------------------------------------------------------------------------
/dsa-questions/leetcode/validate-binary-search-tree/validate-binary-search-tree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://leetcode.com/problems/validate-binary-search-tree/description/
3 | */
4 |
5 | /*
6 | Time Complexity is O(n), where n is the number of nodes in the binary tree.
7 | Space Complexity is O(h), where h is the height of the binary tree
8 | */
9 |
10 | /**
11 | * Definition for a binary tree node.
12 | * function TreeNode(val, left, right) {
13 | * this.val = (val===undefined ? 0 : val)
14 | * this.left = (left===undefined ? null : left)
15 | * this.right = (right===undefined ? null : right)
16 | * }
17 | */
18 | /**
19 | * @param {TreeNode} root
20 | * @return {boolean}
21 | */
22 | var isValidBST = function (root) {
23 | return isBST(root, -Infinity, Infinity);
24 | };
25 |
26 | function isBST(node, lowerBound, upperBound) {
27 | // Base case: An empty tree is a valid BST
28 | if (node === null) {
29 | return true;
30 | }
31 |
32 | // Check current node value against the valid range
33 | if (node.val <= lowerBound || node.val >= upperBound) {
34 | return false;
35 | }
36 |
37 | // Recursively check the left and right subtrees with updated ranges
38 | return (
39 | isBST(node.left, lowerBound, node.val) &&
40 | isBST(node.right, node.val, upperBound)
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/frontend-machine-coding/README.md:
--------------------------------------------------------------------------------
1 | # Frontend Machine Coding Interview Questions in Javascript
2 |
3 | | Problem | Video | Solution |
4 | | --------------------- | ------------------------------------- | ------------------------------- |
5 | | Star Rating Component | [Video](https://youtu.be/QsvPgVV_1Os) | [Solution](./star-rating) |
6 | | Modal Component | [Video](https://youtu.be/E6z42PHIuLA) | [Solution](./modal-component) |
7 | | Carousel Component | [Video](https://youtu.be/qX5qjRnHSnc) | [Solution](./carousel) |
8 | | Accordion Component | [Video](https://youtu.be/iQpX0W18Yb0) | [Solution](./accordion) |
9 | | OTP Input Component | [Video](https://youtu.be/dAvy4OYZpHk) | [Solution](./otp-input) |
10 | | Bishop on Chessboard | [Video](https://youtu.be/aY2ra2BDBd8) | [Solution](./bishop-chessboard) |
11 | | Tabs Component | [Video](https://youtu.be/Q-oCO7so_lc) | [Solution](./tabs) |
12 | | Tic Tac Toe | [Video](https://youtu.be/5u-ENEknLXs) | [Solution](./tic-tac-toe) |
13 | | Todo List | [Video]() | [Solution](./todo-list/) |
14 |
15 | You can check out the above solutions live [here](https://frontend-machine-coding.vercel.app/)
16 |
--------------------------------------------------------------------------------
/frontend-machine-coding/accordion/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Accordion
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/frontend-machine-coding/accordion/scripts/index.js:
--------------------------------------------------------------------------------
1 | import { Accordion } from "./lib.js";
2 |
3 | Accordion({
4 | container: ".accordion-container",
5 | data: [
6 | {
7 | title: "Section 1",
8 | content:
9 | "
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Explicabo quasi officiis, voluptatem id molestiae maiores aliquam ipsa harum, in ratione voluptas! Provident at ducimus nam reiciendis reprehenderit, labore fugit libero.
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Explicabo quasi officiis, voluptatem id molestiae maiores aliquam ipsa harum, in ratione voluptas! Provident at ducimus nam reiciendis reprehenderit, labore fugit libero.