Skip to main content

535. Encode and Decode TinyURL

mediumAsked at Pinterest

Encode and Decode TinyURL is Pinterest's coding-round analog to its production short-link / pin-sharing service. Build a URL shortener: encode(longUrl) returns a short URL; decode(shortUrl) returns the original. The interviewer wants to see you pick a deterministic ID scheme and discuss collision avoidance.

By Sam K., Founder, InterviewChamp.AI · Last verified

Source citations

Public interview reports confirming this problem appears in Pinterest loops.

  • Glassdoor (2026-Q1)Pinterest backend onsite reports cite Tiny URL as a coding-round design problem.
  • LeetCode Pinterest tag (2026-Q1)On the Pinterest company-tagged problem list.

Problem

TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl and it returns a short URL such as http://tinyurl.com/4e9iAk. Design a class with two methods: encode(longUrl) returns a short URL; decode(shortUrl) returns the original long URL. There is no constraint on the encoding/decoding algorithm; the only requirement is that the decoder must restore exactly the URL passed to encode.

Constraints

  • 1 <= url.length <= 10^4
  • url is guaranteed to be a valid URL.

Examples

Example 1

Input
url = 'https://leetcode.com/problems/design-tinyurl'
Output
'https://leetcode.com/problems/design-tinyurl'

Explanation: encode then decode should round-trip the input.

Approaches

1. Hash map with auto-increment counter (optimal for interview)

Maintain a Map<shortId, longUrl> and a counter. encode increments the counter, base-62 encodes the int, stores the mapping, returns 'http://tinyurl.com/{base62}'. decode parses the suffix and looks up.

Time
O(1) amortized both directions
Space
O(N) where N = encoded URLs
class CodecCounter {
  constructor() {
    this.map = new Map();
    this.counter = 0;
    this.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  }
  _base62(n) {
    if (n === 0) return this.alphabet[0];
    let s = '';
    while (n > 0) {
      s = this.alphabet[n % 62] + s;
      n = Math.floor(n / 62);
    }
    return s;
  }
  encode(longUrl) {
    const id = this._base62(this.counter++);
    this.map.set(id, longUrl);
    return 'http://tinyurl.com/' + id;
  }
  decode(shortUrl) {
    const id = shortUrl.split('/').pop();
    return this.map.get(id);
  }
}

Tradeoff: Deterministic ID assignment; no collisions; predictable URL space growth. The counter approach is easy to scale via sharded ID generators (one per server). This is the production-shaped answer.

2. Random 6-character ID + collision retry

Generate a random 6-char base-62 string; if collision, regenerate. Store the mapping.

Time
O(1) expected
Space
O(N)
class CodecRandom {
  constructor() {
    this.map = new Map();
    this.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  }
  _randomId() {
    let s = '';
    for (let i = 0; i < 6; i++) s += this.alphabet[Math.floor(Math.random() * 62)];
    return s;
  }
  encode(longUrl) {
    let id;
    do { id = this._randomId(); } while (this.map.has(id));
    this.map.set(id, longUrl);
    return 'http://tinyurl.com/' + id;
  }
  decode(shortUrl) {
    return this.map.get(shortUrl.split('/').pop());
  }
}

Tradeoff: Trades determinism for non-guessability. 62^6 = 56B IDs, so collisions are rare until ~1M URLs. Production services often combine both — counter-based with a hash perturbation.

Pinterest-specific tips

Pinterest backend interviewers grade three things: (1) you pick a scheme deterministically and explain why; (2) you discuss the counter-vs-random tradeoff (predictability vs guessability); (3) you mention sharded ID generators or pre-allocated ID blocks for horizontal scaling. The fourth signal — security: counter IDs let attackers enumerate all shortened URLs sequentially; random IDs are non-guessable. Volunteer this tradeoff.

Common mistakes

  • Using the long URL itself as the key in a Map (no compression — defeats the purpose).
  • Using a true hash (MD5/SHA) of the URL — same URL re-encoded returns the same short URL, which sounds clever but breaks 'one short per encode call' semantics.
  • Forgetting to handle the case where encode is called twice on the same URL — do you return the same short or a new one? Spec says no constraint; pick one and state it.
  • Storing only the base62 ID and assuming the prefix — write it cleanly with the full short URL.

Follow-up questions

An interviewer at Pinterest may pivot to one of these next:

  • Distributed: how do multiple servers generate non-colliding IDs?
  • Add TTL: short URLs expire after N days.
  • Custom alias support: user wants tinyurl.com/my-pin instead of a random ID.
  • Rate limit encode calls per user.

Solve it now

Free. No sign-up. Python and JavaScript run instantly in your browser.

Output

Press Run or Cmd+Enter to execute

FAQ

Why base-62 specifically?

62 = 26 lowercase + 26 uppercase + 10 digits — the largest alphabet usable in URLs without encoding special characters. Yields short IDs: 62^6 = 56B URLs in 6 chars.

Why does Pinterest care about this problem?

Pinterest shortens pin URLs for sharing and tracks click-through via the shortened form. The encode/decode pair is the production primitive; the follow-ups (TTL, custom aliases, distributed IDs) test real Pinterest infrastructure concerns.

Free learning resources

Curated free links for this problem.

Companies that also ask Encode and Decode TinyURL