Javascript interview coding questions 2024 , basic, intermediate, and advanced levels
30 JavaScript interview coding questions categorized into basic, intermediate, and advanced levels:
Basic:
1. Write a function to reverse a string.
2. Write a function to check if a number is prime.
3. Write a function to find the factorial of a number.
4. Write a function to check if a string is a palindrome.
5. Write a function to remove duplicates from an array.
6. Write a function to find the largest element in an array.
7. Write a function to sort an array of integers in ascending order.
8. Write a function to count the number of vowels in a string.
9. Write a function to calculate the sum of all elements in an array.
10. Write a function to find the second largest number in an array.
Intermediate:
11. Implement a function to perform a binary search on a sorted array.
12. Write a function to merge two sorted arrays into one sorted array.
13. Implement a function to check if two strings are anagrams.
14. Write a function to flatten a nested array.
15. Implement a function to find the nth Fibonacci number.
16. Write a function to check if a given string contains a valid palindrome permutation.
17. Implement a function to perform matrix multiplication.
18. Write a function to find the intersection of two arrays.
19. Implement a function to shuffle an array.
20. Write a function to convert a Roman numeral to an integer.
Advanced:
21. Implement a function to reverse words in a sentence without using built-in methods.
22. Write a function to implement a LRU (Least Recently Used) cache.
23. Implement a function to perform a depth-first search (DFS) on a graph.
24. Write a function to implement a binary tree and perform operations like insert, delete, and search.
25. Implement a function to perform a breadth-first search (BFS) on a graph.
26. Write a function to serialize and deserialize a binary tree.
27. Implement a function to find the longest common subsequence of two strings.
28. Write a function to implement a priority queue.
29. Implement a function to find the shortest path in a weighted graph using Dijkstra’s algorithm.
30. Write a function to implement a binary search tree and perform operations like insert, delete, and search.
1. Reverse a String
function reverseString(str) {
return str.split('').reverse().join('');
}
Explanation: This function takes a string as input, splits it into an array of characters, reverses the array, and then joins the characters back into a string.
2. Check if a Number is Prime
function isPrime(num) {
if (num <= 1) return false;
if (num <= 3) return true;
if (num % 2 === 0 || num % 3 === 0) return false;
let i = 5;
while (i * i <= num) {
if (num % i === 0 || num % (i + 2) === 0) return false;
i += 6;
}
return true;
}
Explanation: This function checks whether a number is prime by iterating from 2 to the square root of the number and checking if it’s divisible by any numbers in that range.
3. Find the Factorial of a Number
function factorial(num) {
if (num === 0 || num === 1) return 1;
let result = 1;
for (let i = 2; i <= num; i++) {
result *= i;
}
return result;
}
Explanation: This function calculates the factorial of a non-negative integer by multiplying all positive integers less than or equal to the given number.
4. Check if a String is a Palindrome
function isPalindrome(str) {
const reversed = str.split('').reverse().join('');
return str === reversed;
}
Explanation: This function checks if a string is a palindrome by comparing the original string with its reverse.
5. Remove Duplicates from an Array
function removeDuplicates(arr) {
return Array.from(new Set(arr));
}
Explanation: This function removes duplicate elements from an array by converting it to a Set (which only contains unique values) and then converting it back to an array.
Title: JavaScript Interview Coding Questions
6. Function to Find the Largest Element in an Array:
function findLargestElement(arr) {
if (arr.length === 0) {
return null; // or handle empty array case as required
}
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
7. Function to Sort an Array of Integers in Ascending Order:
function sortArray(arr) {
return arr.slice().sort((a, b) => a - b);
}
8. Function to Count the Number of Vowels in a String:
function countVowels(str) {
const vowels = ['a', 'e', 'i', 'o', 'u'];
let count = 0;
for (let char of str.toLowerCase()) {
if (vowels.includes(char)) {
count++;
}
}
return count;
}
9. Function to Calculate the Sum of All Elements in an Array:
function calculateSum(arr) {
return arr.reduce((acc, curr) => acc + curr, 0);
}
10. Function to Find the Second Largest Number in an Array:
function findSecondLargest(arr) {
if (arr.length < 2) {
return null; // or handle arrays with less than 2 elements as required
}
let max = arr[0];
let secondMax = arr[1];
if (secondMax > max) {
[max, secondMax] = [secondMax, max];
}
for (let i = 2; i < arr.length; i++) {
if (arr[i] > max) {
secondMax = max;
max = arr[i];
} else if (arr[i] > secondMax) {
secondMax = arr[i];
}
}
return secondMax;
}
11. Binary Search on Sorted Array
Binary search is an efficient algorithm for finding an item from a sorted list of items. It works by repeatedly dividing in half the portion of the list that could contain the item, until you’ve narrowed down the possible locations to just one. Here’s a JavaScript implementation:
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // Not found
}
12. Merge Two Sorted Arrays
Merging two sorted arrays is a common operation. You can do this by iterating through both arrays simultaneously and comparing elements. Here’s how you can do it in JavaScript:
function mergeSortedArrays(arr1, arr2) {
let mergedArray = [];
let i = 0, j = 0;
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
mergedArray.push(arr1[i]);
i++;
} else {
mergedArray.push(arr2[j]);
j++;
}
}
// Add remaining elements from arr1
while (i < arr1.length) {
mergedArray.push(arr1[i]);
i++;
}
// Add remaining elements from arr2
while (j < arr2.length) {
mergedArray.push(arr2[j]);
j++;
}
return mergedArray;
}
13. Check if Two Strings are Anagrams
An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. To check if two strings are anagrams, you can compare their sorted versions. If they are the same, then they are anagrams. Here’s the JavaScript code:
function areAnagrams(str1, str2) {
return str1.split(”).sort().join(”) === str2.split(”).sort().join(”);
}
14. Flatten a Nested Array
Flattening a nested array means to convert a multi-dimensional array into a one-dimensional array. You can achieve this recursively by iterating through the array and checking if each element is an array or not. Here’s a JavaScript implementation:
function flattenArray(arr) {
let flattenedArray = [];
arr.forEach(element => {
if (Array.isArray(element)) {
flattenedArray.push(...flattenArray(element));
} else {
flattenedArray.push(element);
}
});
return flattenedArray;
}
15. Find the nth Fibonacci Number
The Fibonacci sequence is a series of numbers in which each number is the sum of the two preceding ones, usually starting with 0 and 1. Here’s a JavaScript function to find the nth Fibonacci number using recursion:
function fibonacci(n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
Certainly! Below are the solutions to the JavaScript interview coding questions you provided, along with explanations and code implementations.
16. Check for Valid Palindrome Permutation
Explanation:
A string can form a valid palindrome permutation if and only if at most one character occurs an odd number of times (all other characters must occur even times). We can use a hashmap to count the occurrences of each character and then check if there is at most one character with an odd count.
Code:
function isValidPalindromePermutation(str) {
const charCount = new Map();
for (let char of str) {
charCount.set(char, (charCount.get(char) || 0) + 1);
}
let oddCount = 0;
for (let count of charCount.values()) {
if (count % 2 !== 0) {
oddCount++;
if (oddCount > 1) return false;
}
}
return true;
}
// Example usage:
console.log(isValidPalindromePermutation("aab")); // true
console.log(isValidPalindromePermutation("code")); // false
17. Matrix Multiplication
Explanation:
Matrix multiplication involves multiplying the elements of rows of the first matrix with the elements of columns of the second matrix and summing up the results.
Code:
function matrixMultiplication(matrix1, matrix2) {
const result = [];
for (let i = 0; i < matrix1.length; i++) {
result[i] = [];
for (let j = 0; j < matrix2[0].length; j++) {
let sum = 0;
for (let k = 0; k < matrix1[0].length; k++) {
sum += matrix1[i][k] * matrix2[k][j];
}
result[i][j] = sum;
}
}
return result;
}
// Example usage:
const matrix1 = [[1, 2], [3, 4]];
const matrix2 = [[5, 6], [7, 8]];
console.log(matrixMultiplication(matrix1, matrix2)); // Output: [[19, 22], [43, 50]]
18. Intersection of Two Arrays
Explanation:
To find the intersection of two arrays, we can use a Set to store unique elements of one array, and then iterate through the other array to check for elements present in both arrays.
Code:
function intersection(arr1, arr2) {
const set = new Set(arr1);
return arr2.filter(item => set.has(item));
}
// Example usage:
console.log(intersection([1, 2, 2, 1], [2, 2])); // Output: [2, 2]
19. Shuffle an Array
Explanation:
To shuffle an array, we can iterate through each element and swap it with a randomly chosen element in the array.
Code:
function shuffleArray(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]]; // Swap elements
}
return arr;
}
// Example usage:
console.log(shuffleArray([1, 2, 3, 4, 5])); // Output: Shuffled array
20. Convert Roman Numeral to Integer
Explanation:
We can create a hashmap to store the integer equivalents of each Roman numeral. Then, we iterate through the Roman numeral string from left to right, adding the corresponding integer values.
Code:
function romanToInt(roman) {
const romanValues = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
};
let result = 0;
for (let i = 0; i < roman.length; i++) {
if (i > 0 && romanValues[roman[i]] > romanValues[roman[i - 1]]) {
result += romanValues[roman[i]] - 2 * romanValues[roman[i - 1]];
} else {
result += romanValues[roman[i]];
}
}
return result;
}
// Example usage:
console.log(romanToInt('III')); // Output: 3
console.log(romanToInt('IV')); // Output: 4
21. Reverse Words in a Sentence (JavaScript)
function reverseWords(sentence) {
let reversedSentence = '';
let word = '';
for (let i = 0; i < sentence.length; i++) {
if (sentence[i] === ' ') {
reversedSentence = word + ' ' + reversedSentence;
word = '';
} else {
word += sentence[i];
}
}
reversedSentence = word + ' ' + reversedSentence;
return reversedSentence.trim();
}
const sentence = "Implement a function to reverse words";
console.log(reverseWords(sentence));
22. LRU Cache Implementation (JavaScript)
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key); // Delete and re-insert to make it most recently used
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key); // Delete and re-insert to make it most recently used
} else if (this.cache.size === this.capacity) {
// Delete the least recently used item
const leastRecentlyUsed = this.cache.keys().next().value;
this.cache.delete(leastRecentlyUsed);
}
this.cache.set(key, value);
}
}
// Example usage
const cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1)); // Output: 1
cache.put(3, 3); // Evicts key 2
console.log(cache.get(2)); // Output: -1
23. Depth-First Search (DFS) on a Graph (JavaScript)
class Graph {
constructor() {
this.vertices = [];
this.adjList = new Map();
}
addVertex(v) {
this.vertices.push(v);
this.adjList.set(v, []);
}
addEdge(v, w) {
this.adjList.get(v).push(w);
this.adjList.get(w).push(v); // For undirected graph
}
dfs(startingNode) {
const visited = {};
this.dfsUtil(startingNode, visited);
}
dfsUtil(vertex, visited) {
visited[vertex] = true;
console.log(vertex);
const neighbors = this.adjList.get(vertex);
for (let i = 0; i < neighbors.length; i++) {
const neighbor = neighbors[i];
if (!visited[neighbor]) {
this.dfsUtil(neighbor, visited);
}
}
}
}
// Example usage
const graph = new Graph();
const vertices = ['A', 'B', 'C', 'D', 'E', 'F'];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge('A', 'B');
graph.addEdge('A', 'D');
graph.addEdge('B', 'C');
graph.addEdge('D', 'E');
graph.addEdge('E', 'F');
graph.dfs('A');
24. Binary Tree Implementation (JavaScript)
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
class BinaryTree {
constructor() {
this.root = null;
}
insert(value) {
const newNode = new TreeNode(value);
if (!this.root) {
this.root = newNode;
return;
}
let current = this.root;
while (true) {
if (value < current.value) {
if (!current.left) {
current.left = newNode;
return;
}
current = current.left;
} else {
if (!current.right) {
current.right = newNode;
return;
}
current = current.right;
}
}
}
search(value) {
let current = this.root;
while (current) {
if (value === current.value) {
return true;
} else if (value < current.value) {
current = current.left;
} else {
current = current.right;
}
}
return false;
}
delete(value) {
// Left as an exercise
}
}
// Example usage
const tree = new BinaryTree();
tree.insert(5);
tree.insert(3);
tree.insert(7);
console.log(tree.search(3)); // Output: true
console.log(tree.search(10)); // Output: false
25. Breadth-First Search (BFS) on a Graph (JavaScript)
class Graph {
constructor() {
this.vertices = [];
this.adjList = new Map();
}
addVertex(v) {
this.vertices.push(v);
this.adjList.set(v, []);
}
addEdge(v, w) {
this.adjList.get(v).push(w);
this.adjList.get(w).push(v); // For undirected graph
}
bfs(startingNode) {
const visited = {};
const queue = [];
visited[startingNode] = true;
queue.push(startingNode);
while (queue.length) {
const vertex = queue.shift();
console.log(vertex);
const neighbors = this.adjList.get(vertex);
for (let i = 0; i < neighbors.length; i++) {
const neighbor = neighbors[i];
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.push(neighbor);
}
}
}
}
}
// Example usage
const graph = new Graph();
const vertices = ['A', 'B', 'C', 'D', 'E', 'F'];
for (let i = 0; i < vertices.length; i++) {
graph.addVertex(vertices[i]);
}
graph.addEdge('A', 'B');
graph.addEdge('A', 'D');
graph.addEdge('B', 'C');
graph.addEdge('D', 'E');
graph.addEdge('E', 'F');
graph.bfs('A');
26. Serialize and Deserialize a Binary Tree
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
function serialize(root) {
if (!root) return 'null';
return `${root.val},${serialize(root.left)},${serialize(root.right)}`;
}
function deserialize(data) {
const nodes = data.split(',');
return buildTree(nodes);
}
function buildTree(nodes) {
const val = nodes.shift();
if (val === 'null') return null;
const node = new TreeNode(parseInt(val));
node.left = buildTree(nodes);
node.right = buildTree(nodes);
return node;
}
27. Longest Common Subsequence of Two Strings
function longestCommonSubsequence(text1, text2) {
const m = text1.length;
const n = text2.length;
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (text1[i - 1] === text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
let i = m, j = n;
const result = [];
while (i > 0 && j > 0) {
if (text1[i - 1] === text2[j - 1]) {
result.unshift(text1[i - 1]);
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
} else {
j--;
}
}
return result.join('');
}
28. Priority Queue
class PriorityQueue {
constructor() {
this.queue = [];
}
enqueue(item, priority) {
this.queue.push({ item, priority });
this.queue.sort((a, b) => a.priority - b.priority);
}
dequeue() {
if (this.isEmpty()) return null;
return this.queue.shift().item;
}
isEmpty() {
return this.queue.length === 0;
}
}
29. Shortest Path in Weighted Graph using Dijkstra’s Algorithm
function dijkstra(graph, start) {
const distances = {};
const visited = {};
const queue = new PriorityQueue();
for (let vertex in graph) {
distances[vertex] = vertex === start ? 0 : Infinity;
queue.enqueue(vertex, distances[vertex]);
}
while (!queue.isEmpty()) {
const currentVertex = queue.dequeue();
for (let neighbor in graph[currentVertex]) {
const distance = distances[currentVertex] + graph[currentVertex][neighbor];
if (distance < distances[neighbor]) {
distances[neighbor] = distance;
queue.enqueue(neighbor, distance);
}
}
visited[currentVertex] = true;
}
return distances;
}
30. Binary Search Tree Operations
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(val) {
const newNode = new TreeNode(val);
if (!this.root) {
this.root = newNode;
return this;
}
let current = this.root;
while (true) {
if (val === current.val) return undefined;
if (val < current.val) {
if (!current.left) {
current.left = newNode;
return this;
}
current = current.left;
} else {
if (!current.right) {
current.right = newNode;
return this;
}
current = current.right;
}
}
}
search(val) {
let current = this.root;
while (current) {
if (val === current.val) return true;
if (val < current.val) {
current = current.left;
} else {
current = current.right;
}
}
return false;
}
remove(val) {
const removeNode = (node, val) => {
if (!node) {
return null;
}
if (val === node.val) {
if (!node.left && !node.right) {
return null;
}
if (!node.left) {
return node.right;
}
if (!node.right) {
return node.left;
}
let tempNode = node.right;
while (tempNode.left) {
tempNode = tempNode.left;
}
node.val = tempNode.val;
node.right = removeNode(node.right, tempNode.val);
return node;
} else if (val < node.val) {
node.left = removeNode(node.left, val);
return node;
} else {
node.right = removeNode(node.right, val);
return node;
}
};
this.root = removeNode(this.root, val);
}
}