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 Alex Chen, 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.

Practice these live with InterviewChamp.AI

Drill Encode and Decode TinyURL and other Pinterest interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.

Practice these live with InterviewChamp.AI →