Solve in the language of your choice (practice in both JS and Java if you can).
A1. Given an array of integers, return the two indices whose values sum to a target. Assume exactly one solution exists.
Input: nums = [2, 7, 11, 15], target = 9
Output: [0, 1]
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> seen = new HashMap<>(); // build hashmap storing value -> index
for(int i=0; i < nums.length; i++){
int complement = target - nums[i];
if (seen.containsKey(complement)) { // check if index target-nums[i] exists
return new int[] { seen.get(complement), i };
}
seen.put(nums[i], i);
}
throw new IllegalArgumentException("No solution found"); // error
}
A2. Given a string, determine if it's a valid palindrome, ignoring non-alphanumeric characters and case.
Input: "A man, a plan, a canal: Panama"
Output: true
public boolean isPalindrome(String str) {
int left = 0; // two pointer from both ends
int right = s.length() - 1;
while (left < right){
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) left++; // skip non-alphanumeric chars
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) right--;
if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) { // compare lowercase values
return false;
}
left++;
right--;
}
return true;
}
A3. Given a string of parentheses ()[]{}, determine if the brackets are balanced.
Input: "([{}])"
Output: true
Input: "([)]"
Output: false
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>(); // build stack
Map<Character, Character> pairs = Map.of(')', '(', ']', '[', '}', '{'); //build map close -> open bracket
for (char c : s.toCharArray()) {
if (pairs.containsKey(c)) { // pop and match on closing bracket
if (stack.isEmpty() || stack.pop() != pairs.get(c)) {
return false;
}
} else {
stack.push(c);
}
}
return stack.isEmpty(); // all characters fit a valid pair
}
A4. Given an array, find the length of the longest subarray with no repeating elements (sliding window).
Input: [2, 1, 5, 1, 3, 2]
Output: 3 (e.g. [5,1,3])
// Sliding window with a Set or index map tracking last-seen position of each element;
// shrink window from the left when a duplicate is found
public int longestUniqueSubarray(int[] nums) {
Map<Integer, Integer> lastSeen = new HashMap<>(); // map element -> last seen
int maxLen = 0, left = 0; // sliding window
for (int right = 0; right < nums.length; right++) {
if (lastSeen.containsKey(nums[right]) && lastSeen.get(nums[right]) >= left) {
left = lastSeen.get(nums[right]) + 1;
}
lastSeen.put(nums[right], right);
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
A5. Given a binary tree, return the maximum depth.
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) { this.val = val; }
}
// Recursive: 1 + max(depth(left), depth(right)), base case null returns 0
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
B1. Explain the difference between process.nextTick(), setImmediate(), and setTimeout(fn, 0). What order do they run in?
console.log('start');
setTimeout(() => console.log('setTimeout'), 0);
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick'));
console.log('end');
// Output:
// start
// end
// nextTick <- runs before the event loop continues
// setTimeout <- order vs setImmediate isn't guaranteed here
// setImmediate
B2. Write a small piece of Express middleware that logs the request method and URL, then calls next().
app.use((req, res, next) => { console.log(req.method, req.url); next(); });
const express = require('express');
const app = express();
function logger(req, res, next) {
console.log(`${req.method} ${req.url}`);
next();
}
app.use(logger);
app.get('/', (req, res) => res.send('Hello'));
app.listen(3000);