JavaScript Arrays
Arrays in JavaScript are a fundamental data structure used to store lists of values. Arrays can hold elements of any data type, including numbers, strings, objects, and even other arrays. They are zero-indexed, meaning the first element has an index of 0.
Concept and Use Cases
Definition: A JavaScript array is an ordered, mutable collection of values, where each value is identified by an index. Arrays can grow and shrink dynamically, and they come with a rich set of methods for performing various operations.
Common Use Cases:
- Storing lists of items (e.g., a list of names, numbers).
- Representing collections of data in applications.
- Implementing data structures like stacks and queues.
- Performing operations like sorting, filtering, and mapping.
When to Use
- When you need to store multiple values in a single variable.
- When the order of elements is important.
- When you need to perform operations on collections of data.
Time and Space Complexity
Time Complexity:
- Access: O(1) (constant time access to elements by index)
- Insertion/Deletion at the end: O(1)
- Insertion/Deletion at the beginning: O(n) (requires shifting elements)
- Searching: O(n) (linear search)
Space Complexity:
- O(n) (proportional to the number of elements in the array)
Array Operations and Methods
Creating Arrays
Example:
let emptyArray = [];
let numberArray = [1, 2, 3, 4, 5];
let mixedArray = [1, 'two', {three: 3}, [4, 5]];
let arrayWithConstructor = new Array(10); // Creates an array with 10 empty slots
Accessing Elements
Example:
let arr = [10, 20, 30, 40, 50];
console.log(arr[0]); // Output: 10
console.log(arr[3]); // Output: 40
Modifying Elements
Example:
let arr = [1, 2, 3];
arr[0] = 10;
arr[2] = 30;
console.log(arr); // Output: [10, 2, 30]
Adding and Removing Elements
Example:
let arr = [1, 2, 3];
arr.push(4); // Adds to the end
console.log(arr); // Output: [1, 2, 3, 4]
arr.pop(); // Removes from the end
console.log(arr); // Output: [1, 2, 3]
arr.unshift(0); // Adds to the beginning
console.log(arr); // Output: [0, 1, 2, 3]
arr.shift(); // Removes from the beginning
console.log(arr); // Output: [1, 2, 3]
Array Length
Example:
let arr = [1, 2, 3];
console.log(arr.length); // Output: 3
arr.length = 5; // Resizes the array
console.log(arr); // Output: [1, 2, 3, <2 empty slots>]
Iterating Over Arrays
Example:
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
arr.forEach((element, index) => {
console.log(element, index);
});
Array Methods
Example:
let arr = [1, 2, 3, 4, 5];
// Map
let doubled = arr.map(x => x * 2);
console.log(doubled); // Output: [2, 4, 6, 8, 10]
// Filter
let evens = arr.filter(x => x % 2 === 0);
console.log(evens); // Output: [2, 4]
// Reduce
let sum = arr.reduce((acc, x) => acc + x, 0);
console.log(sum); // Output: 15
// Find
let firstEven = arr.find(x => x % 2 === 0);
console.log(firstEven); // Output: 2
// Some
let hasEven = arr.some(x => x % 2 === 0);
console.log(hasEven); // Output: true
// Every
let allEven = arr.every(x => x % 2 === 0);
console.log(allEven); // Output: false
// Slice
let subArray = arr.slice(1, 3);
console.log(subArray); // Output: [2, 3]
// Splice
arr.splice(2, 1, 'a', 'b');
console.log(arr); // Output: [1, 2, 'a', 'b', 4, 5]
// Concat
let arr2 = [6, 7, 8];
let concatenated = arr.concat(arr2);
console.log(concatenated); // Output: [1, 2, 'a', 'b', 4, 5, 6, 7, 8]
Practical Tips and Tricks
-
Using
Array.fromandArray.of: Create arrays from array-like objects or individual elements.Example:
let str = 'hello'; let arr = Array.from(str); console.log(arr); // Output: ['h', 'e', 'l', 'l', 'o'] let arr2 = Array.of(1, 2, 3); console.log(arr2); // Output: [1, 2, 3] -
Filling Arrays: Use
fillto initialize or reset arrays.Example:
let arr = new Array(5).fill(0); console.log(arr); // Output: [0, 0, 0, 0, 0] -
Flattening Arrays: Use
flatto flatten nested arrays.Example:
let nestedArr = [1, [2, [3, 4], 5]]; let flatArr = nestedArr.flat(2); console.log(flatArr); // Output: [1, 2, 3, 4, 5] -
Removing Duplicates: Use
Setto remove duplicates from an array.Example:
let arr = [1, 2, 2, 3, 3, 4]; let uniqueArr = Array.from(new Set(arr)); console.log(uniqueArr); // Output: [1, 2, 3, 4]
Common Gotchas
-
Sparse Arrays: Assigning to indices beyond the current length can create sparse arrays.
Example:
let arr = [1, 2, 3]; arr[10] = 11; console.log(arr); // Output: [1, 2, 3, <7 empty slots>, 11] -
Array-Like Objects: Objects like
argumentsand DOM NodeLists are not true arrays but can be converted.Example:
function example() { let args = Array.from(arguments); console.log(args); } example(1, 2, 3); // Output: [1, 2, 3] -
Mutating Methods: Methods like
splice,sort, andreversemutate the original array.Example:
let arr = [1, 2, 3]; arr.reverse(); console.log(arr); // Output: [3, 2, 1]
Advanced Topics
Typed Arrays
Typed Arrays provide a way to handle binary data directly in JavaScript. They are used in scenarios like working with raw binary data or interacting with Web APIs.
Example:
let buffer = new ArrayBuffer(16);
let int32View = new Int32Array(buffer);
int32View[0] = 42;
console.log(int32View); // Output: Int32Array [ 42, 0, 0, 0 ]
ArrayBuffer and DataView
ArrayBuffer is a generic, fixed-length binary data buffer, and DataView provides a low-level interface for reading and writing multiple number types in an ArrayBuffer.
Example:
let buffer = new ArrayBuffer(16);
let view = new DataView(buffer);
view.setInt8(0, 127);
console.log(view.getInt8(0)); // Output: 127
Advanced Array Methods
Example:
// FlatMap
let arr = [1, 2, 3, 4];
let result = arr.flatMap(x => [x, x * 2]);
console.log(result); // Output: [1, 2, 2, 4, 3, 6, 4, 8]
// ReduceRight
let arr2 = [1, 2, 3, 4];
let result2 = arr2.reduceRight((acc, x) => acc - x, 0);
console.log(result2); // Output: -10
// Entries, Keys, Values
let arr3 = ['a', 'b', 'c'];
for (let [index, element] of arr3.entries()) {
console.log(index, element);
}
for (let key of arr3.keys()) {
console.log(key);
}
for (let value of arr3.values()) {
console.log(value);
}
Array Algorithms
Below are some common array algorithms you should be familiar with:
Sorting
Sorting an array involves arranging the elements in a specific order, typically ascending or descending.
Example:
let arr = [3, 1, 4, 1, 5, 9];
arr.sort((a, b) => a - b);
console.log(arr); // Output: [1, 1, 3, 4, 5, 9]
Searching
Searching an array is about finding elements that meet certain criteria.
Example:
let arr = [10, 20, 30, 40, 50];
let found = arr.find(x => x > 25);
console.log(found); // Output: 30
Merging Arrays
Merging arrays involves combining two or more arrays into one.
Example:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let merged = [...arr1, ...arr2];
console.log(merged); // Output: [1, 2, 3, 4, 5, 6]
Reversing Arrays
Reversing an array changes the order of its elements to the opposite direction.
Example:
let arr = [1, 2, 3];
arr.reverse();
console.log(arr); // Output: [3, 2, 1]
Rotating Arrays
Rotating an array shifts its elements to the left or right by a specified number of positions.
Example:
function rotateArray(arr, k) {
k = k % arr.length;
return [...arr.slice(-k), ...arr.slice(0, -k)];
}
let arr = [1, 2, 3, 4, 5];
console.log(rotateArray(arr, 2)); // Output: [4, 5, 1, 2, 3]
Interview Tips and Tricks
-
Understand Array Mutability: Know which methods mutate the array and which return a new array. This is crucial for writing efficient and bug-free code.
-
Master Higher-Order Functions: Familiarize yourself with
map,filter,reduce, and other higher-order functions. These are often used in interview problems. -
Practice Common Algorithms: Be comfortable with algorithms involving arrays, such as searching, sorting, and manipulating subarrays.
-
Edge Cases: Always consider edge cases like empty arrays, arrays with a single element, and arrays with duplicate values.
Common Mistakes
-
Off-by-One Errors: Be cautious with indices, especially in loops and when slicing arrays.
-
Mutating Arrays Unintentionally: Understand when methods like
splice,sort, andreversemodify the original array. -
Incorrect Use of Higher-Order Functions: Misunderstanding the behavior of
map,filter, andreducecan lead to logic errors in your code. -
Not Handling Sparse Arrays Properly: Be aware of the implications of creating sparse arrays, especially when using methods like
Arraywith a constructor argument.
By mastering JavaScript arrays and understanding their intricacies, you will be well-equipped to handle a variety of interview questions and real-world problems involving collections of data. Regular practice and a solid grasp of advanced topics will deepen your understanding and improve your problem-solving skills.
Practice Problems
Given the prices of a single stock over time, find the optimal day to buy and sell the stock to maximize profit while avoiding losses.
function maxProfit(prices: number[]): number {
let ans = 0;
let mi = prices[0];
for (const v of prices) {
ans = Math.max(ans, v - mi);
mi = Math.min(mi, v);
}
return ans;
}
Given two pointers representing the start and end of a container, find the maximum area that can be trapped between the two "walls" represented by the pointer positions.
function maxArea(height: number[]): number {
let i = 0;
let j = height.length - 1;
let ans = 0;
while (i < j) {
const t = Math.min(height[i], height[j]) * (j - i);
ans = Math.max(ans, t);
if (height[i] < height[j]) {
++i;
} else {
--j;
}
}
return ans;
}
The task is to efficiently sort an array of colored integers, where each integer represents the color with values ranging from 0 (black) to 2 (white), in ascending order of their corresponding colors.
/**
Do not return anything, modify nums in-place instead.
*/
function sortColors(nums: number[]): void {
let i = -1;
let j = nums.length;
let k = 0;
while (k < j) {
if (nums[k] === 0) {
++i;
[nums[i], nums[k]] = [nums[k], nums[i]];
++k;
} else if (nums[k] === 2) {
--j;
[nums[j], nums[k]] = [nums[k], nums[j]];
} else {
++k;
}
}
}
Write an algorithm to calculate the product of all numbers in an array, excluding the number at each index, for a given input array of integers.
function productExceptSelf(nums: number[]): number[] {
return nums.map((_, i) => nums.reduce((pre, val, j) => pre * (i === j ? 1 : val), 1));
}
Given an array and an integer target sum, find all unique subarrays within the array that sum up to the target value.
function subarraySum(nums: number[], k: number): number {
const cnt: Map<number, number> = new Map();
cnt.set(0, 1);
let [ans, s] = [0, 0];
for (const x of nums) {
s += x;
ans += cnt.get(s - k) || 0;
cnt.set(s, (cnt.get(s) || 0) + 1);
}
return ans;
}
Let's continue exploring the next page. Take your time, and proceed when you're ready.