Explain memoization.

Memoization caches function results based on input arguments, avoiding redundant calculations. It’s useful in recursive algorithms and data-heavy applications.

const memoize = (fn) => {
  const cache = {};
  return (...args) => {
    const key = JSON.stringify(args);
    return cache[key] || (cache[key] = fn(...args));
  };
};