Skip to content

Instantly share code, notes, and snippets.

@andriilive
Last active February 28, 2025 15:00
Show Gist options
  • Save andriilive/36551002aa8f746fdca9efdf9e5ec26e to your computer and use it in GitHub Desktop.
Save andriilive/36551002aa8f746fdca9efdf9e5ec26e to your computer and use it in GitHub Desktop.
Full-stack interview cheatsheet 2025 (React / TS)

CheatSheets

Interview questions

Event loop

See JavaScript Visualized - Event Loop, Web APIs, (Micro)task Queue
https://www.youtube.com/watch?v=eiC58R16hb8

  1. Call stack

  2. Micro task queue:

Event loop prioritize micro tasks queue

CleanShot 2025-02-20 at 20 36 38@2x

CleanShot 2025-02-20 at 20 37 32@2x

  1. Task queue:

CleanShot 2025-02-20 at 20 35 22@2x

Example:

console.log('console.log'); // 0

Promise.resolve().then(() => console.log('Promise resolve')); // 1

queueMicrotask(() => {
  console.log('queueMicrotask'); // 2
  queueMicrotask(() => { console.log('queueMicrotask inner'); }); // 3
});

setTimeout (() => console.log('setTimeout 0'), 0); // 4
setTimeout (() => console.log('setTimeout 10'), 10); // 5

Algorithms & time complexity

See: Algorithms and Data Structures Tutorial - Full Course for Beginners
https://youtu.be/8hly31xKli0?si=eE81Fdz6gpcHz5qG (5 hours)

Big O:

image

Interview tasks

Some real tasks

01 Aliasing

const x = {};
const y = x; // alias

setValue(y);
console.log('setValueX', x); // {val: 10}
console.log('setValueY', y); // {val: 10}

setNotNull(y);
console.log('setNotNullX', x); // {val: 10}
console.log('setNotNullY', y); // {val: 10}

setNull(y);
console.log('setNullX', x); // {val: null}
console.log('setNullY', y); // {val: null}

function setValue(param) {
  param.val = 10;
}

function setNotNull(param) {
  param = null;
}

function setNull(param) {
  param.val = null;
}

02 Second biggest

const arr0 = [4, 3, 8, 5, 10, 6, 7];
const arr1 = [4, 3, 2, 10, 6, 8, 7];
const arr2 = [8, 4, 10, 3, 2];
const arr3 = [10, 4, 8, 3, 2];

// Sorting 
// Time complicity: O(n log n)

function secondBiggest(arr) {
	var set = new Set(arr); // O(n)
	var sorted = [...set].sort((a, b) => b-a); //  O(n log n)
  return sorted.length > 1 ? sorted[1] : sorted[0]; // O(1)
}

console.log(secondBiggest(arr0));
console.log(secondBiggest(arr1));
console.log(secondBiggest(arr2));
console.log(secondBiggest(arr3));

// Time complicity: O(n)

function secondBiggestOn(arr) {
    let max = -Infinity, secondMax = -Infinity;

    for (let num of arr) {
        if (num > max) {
            secondMax = max;
            max = num;
        } else if (num > secondMax && num < max) {
            secondMax = num;
        }
    }

    return secondMax;
}

console.log('-------------------');

console.log(secondBiggestOn(arr0));
console.log(secondBiggestOn(arr1));
console.log(secondBiggestOn(arr2));
console.log(secondBiggestOn(arr3));

03 Count between

Given an array of integers and a series of ranges, determine the number of array elements in the ranges. The ranges are inclusive.

Example

arr = [1, 2, 2, 3, 4]
low = [0, 2]
high = [2, 4]

Queries are aligned by index.

  1. low = 0, high = 2: There are 3 elements in the range: [1, 2, 2]
  2. low = 2, high = 4: There are 4 elements in the range: [2, 2, 3, 4]

Return the array of answers, aligned by index with their queries: [3, 4]

Constraints

  • 1≤n≤ 105
  • 1 ≤ arril≤ 109
  • 1≤9≤105
  • 1 ≤ lowli] ≤ high[i] ≤ 10°
function countBetween(arr: number[], low: number[], high: number[]): number[] {
    // Step 1: Sort the input array
    arr.sort((a, b) => a - b);

    // Helper function to find elements within a range using binary search
    const countInRange = (start: number, end: number): number => {
        const lowerIndex = lowerBound(arr, start);
        const upperIndex = upperBound(arr, end);
        return upperIndex - lowerIndex;
    };

    // Binary search to find the first index where element >= target
    const lowerBound = (array: number[], target: number): number => {
        let left = 0, right = array.length;
        while (left < right) {
            const mid = Math.floor((left + right) / 2);
            if (array[mid] >= target) right = mid;
            else left = mid + 1;
        }
        return left;
    };

    // Binary search to find the first index where element > target
    const upperBound = (array: number[], target: number): number => {
        let left = 0, right = array.length;
        while (left < right) {
            const mid = Math.floor((left + right) / 2);
            if (array[mid] > target) right = mid;
            else left = mid + 1;
        }
        return left;
    };

    // Step 2: Process each query and get results
    const results: number[] = [];
    for (let i = 0; i < low.length; i++) {
        results.push(countInRange(low[i], high[i]));
    }

    return results;
}

// Example usage
const arr = [1, 3, 5, 6, 8];
const low = [2];
const high = [6];
console.log(countBetween(arr, low, high)); // Output: [3]

SQL fees calculations

Compute the year-end account balance for a customer based on the contents of the database table transactions, which houses transaction records for the year 2020.

The account begins with a balance of zero and undergoes various transactions throughout the year. Positive amounts denote deposits or credits, with no associated fees. Negative amounts represent debit transactions, such as credit card charges or withdrawals, impacting the monthly fee calculation.

Monthly fees are structured as follows:

  • If there are fewer than 20 debit transactions or their combined total is less than 1000, a fee of 5 is charged.
  • For 20 to 25 debit transactions, a fee of 3 applies.
  • If there are more than 25 debit transactions, no monthly fee is levied.

Compute the year-end balance in the account by summing up all credits and debits, adjusting for monthly fees based on the criteria mentioned above.

Data example:

CleanShot 2025-02-20 at 20 11 40@2x

The data in the sample table is limited to January, but the full table includes data for all months of 2020. There are 882.56 in debits in 18 transactions. Either of these values results in a fee of 5 for the month. There are 94.15 in payments to the account. The amount owed to the credit card company is 882.56 + 5 - 94.15 = 793.41

Expected result:

CleanShot 2025-02-20 at 20 13 13@2x

WITH monthly_transactions AS (
    SELECT 
        DATE_FORMAT(dt, '%m') AS month,
        COUNT(CASE WHEN amount < 0 THEN 1 END) AS debit_count,
        SUM(CASE WHEN amount < 0 THEN ABS(amount) ELSE 0 END) AS total_debits,
	SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) AS total_payments
    FROM transactions
    WHERE dt LIKE '2020-%' # OPTIONALLY: FILTER BY YEAR OR MOUNTH
    GROUP BY DATE_FORMAT(dt, '%m')
),
monthly_fees AS (
    SELECT 
        month,
        CASE 
            WHEN debit_count < 20 OR total_debits < 1000 THEN 5
            WHEN debit_count BETWEEN 20 AND 25 THEN 3
            ELSE 0
        END AS monthly_fee
    FROM monthly_transactions
),
yearly_balance AS (
    SELECT 
        SUM(total_debits) + SUM(monthly_fee) - SUM(total_payments) AS final_balance
    FROM monthly_transactions
    JOIN monthly_fees USING (month)
)

SELECT ROUND(final_balance, 2) AS balance
FROM yearly_balance;

Typescript fetch

Run with bun run api.ts

type Country = {
  callingCodes: string[] | [];
  [key: string]: unknown;
};

type PhoneApiResponse = {
  page: number;
  per_page: number;
  total: number;
  total_pages: number;
  data: Country[] | [];
};

async function getPhoneNumbers(country: string, phoneNumber: string): Promise<string> {
  try {
    const encodedCountry = encodeURIComponent(country);
    const response = await fetch(`https://jsonmock.hackerrank.com/api/countries?name=${encodedCountry}`);

    // Перевірка статусу відповіді
    if (!response.ok) {
      return '-1';  // Якщо статус відповіді не '200', повертаємо '-1'
    }

    // Перетворення відповіді у формат JSON
    const responseData : PhoneApiResponse = await response.json();

    // Перевірка наявності ключа 'data'
    if (!Object.prototype.hasOwnProperty.call(responseData, 'data')) {
      return '-1';  // Якщо ключа 'data' немає, повертаємо '-1'
    }

    // Перевірка наявності даних у ключі 'data'
    const { data } = responseData;
    if (!Array.isArray(data) || data.length === 0) {
      return '-1';  // Якщо масив порожній або відсутній, повернути '-1'
    }

    // Отримання коду країни
    const callingCodes = data[0].callingCodes;
    if (!Array.isArray(callingCodes) || callingCodes.length === 0) {
      return '-1';  // Якщо коди відсутні або не є масивом, повернути '-1'
    }

    // Використання останнього коду зі списку
    const callingCode = callingCodes[callingCodes.length - 1];

    // Формування результату
    return `+${callingCode} ${phoneNumber}`
  } catch (error) {
    console.error('Error:', error);
    return '-1';
  }
}

const testData : {
  name: string;
  phoneNumber: string;
}[] = [
  {
    name: 'Ukraine',
    phoneNumber: '506066666'
  },
  {
    name: 'Czech Republic',
    phoneNumber: '777777777'
  },
  {
    name: 'Afghanistan',
    phoneNumber: '656445445'
  }
]

for (const testItem of testData) {
  getPhoneNumbers(testItem.name, testItem.phoneNumber).then((result) => {
    console.log(result);
  });
}

React search param sync hook

import {useState} from "react";
import {useNavigate, useSearchParams} from "react-router-dom";

export function useHrefParamHook(param: string = "rate", defaultValue: string) : [
  string, (s: string) => void
] {
  // if (!window) {
  //   throw new Error("search params can't be used in server components");
  // }
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const rate = searchParams.get(param);
  const [rateState, _setRateState] = useState(rate ? rate : defaultValue);

  const setRateState = (rate: string) => {
    _setRateState(rate);
    navigate(window.location.pathname + `?${param}=` + rate, {
      replace: true
    });
  }

  return [
    rateState,
    setRateState
  ]
}

Str to array

console.log(Array.from('Example'));
console.log(Array.from('Educative!'));

const num = 1234;

console.log(Array.from([...`${num}`].map((el)=>Number(el))));
console.log(Array.from(`${num}`)); // strvals
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment