{
  "id": "hashing/sets",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/hashing/sets",
  "topic": {
    "slug": "hashing",
    "title": "Hashing"
  },
  "title": "Sets",
  "tagline": "A hash map that threw away the values — and answers 'seen this before?' instantly.",
  "vizKind": "hash",
  "complexity": {
    "time": {
      "best": "O(1)",
      "average": "O(1)",
      "worst": "O(n)"
    },
    "space": "O(n)",
    "growth": "constant",
    "note": "add, has and delete are all O(1) on average — one hash, one jump. The worst case is O(n) if every key collides into one bucket, exactly as with a hash map. You are paying O(n) memory to turn an O(n²) scan into an O(n) one."
  },
  "code": {
    "javascript": "// A Set is a hash map that threw away the values\n// and kept only the keys.\nconst seen = new Set();\n\nfunction hasDuplicate(a) {\n  for (const v of a) {\n    if (seen.has(v)) return true;   // O(1) — one hash, one look\n    seen.add(v);                    // O(1)\n  }\n  return false;\n}\n\n// The nested-loop version is O(n²). This is O(n).",
    "python": "# A set is a dict that threw away the values\n# and kept only the keys.\ndef has_duplicate(a):\n    seen = set()\n\n    for v in a:\n        if v in seen: return True    # O(1) — one hash, one look\n        seen.add(v)                  # O(1)\n\n    return False\n\n\n# The nested-loop version is O(n²). This is O(n).\n",
    "java": "// A Set is a HashMap that threw away the values\n// and kept only the keys.\nboolean hasDuplicate(int[] a) {\n  Set<Integer> seen = new HashSet<>();\n\n  for (int v : a) {\n    if (seen.contains(v)) return true;  // O(1)\n    seen.add(v);                        // O(1)\n  }\n\n  return false;\n}\n\n// The nested-loop version is O(n²). This is O(n).",
    "cpp": "// A set is a hash map that threw away the values\n// and kept only the keys.\nbool hasDuplicate(vector<int>& a) {\n  unordered_set<int> seen;\n\n  for (int v : a) {\n    if (seen.count(v)) return true;     // O(1)\n    seen.insert(v);                     // O(1)\n  }\n\n  return false;\n}\n\n// The nested-loop version is O(n²). This is O(n)."
  },
  "defaultInput": [
    17,
    22,
    3,
    8,
    12,
    22
  ],
  "defaultTarget": null,
  "inputHint": "Walk the list once, asking 'seen it?' each time. The 22 comes back.",
  "pitfalls": [
    {
      "wrong": "Expecting a set to remember insertion order.",
      "right": "It scatters keys by hash, not by when they arrived. If order matters, you need a list alongside it — or an ordered/linked set."
    },
    {
      "wrong": "Using a set when you need to store a value with the key.",
      "right": "That's a hash map. A set only records that a key exists. 'Have I seen it?' — set. 'What was it worth?' — map."
    },
    {
      "wrong": "Putting mutable objects in a set and then changing them.",
      "right": "The hash was computed when it went in. Change the object and its hash changes — so the set can no longer find it, even though it's sitting right there."
    }
  ],
  "quiz": [
    {
      "q": "What is a set, really?",
      "options": [
        "A sorted list with no duplicates",
        "A hash map that keeps only the keys and throws the values away",
        "A tree",
        "An array with a special flag"
      ],
      "answer": 1,
      "why": "Exactly that. It's the same hashing machinery, minus the stored values — which is why 'is this in the set?' is O(1), just like a map lookup."
    },
    {
      "q": "How does a set turn 'does this list have a duplicate?' from O(n²) into O(n)?",
      "options": [
        "It sorts the list first",
        "It walks the list once, and each 'have I seen this?' is O(1)",
        "It uses recursion",
        "It doesn't — it's still O(n²)"
      ],
      "answer": 1,
      "why": "The nested-loop version compares every pair. With a set you make one pass and ask an O(1) question at each element — n × O(1) = O(n)."
    },
    {
      "q": "What does a set NOT give you?",
      "options": [
        "Fast membership testing",
        "Order, and values stored alongside the keys",
        "Uniqueness",
        "O(1) insertion"
      ],
      "answer": 1,
      "why": "No order (it scatters keys by hash) and no associated values (that's a hash map). Those absences are exactly what make it so small and fast."
    }
  ],
  "problems": [
    {
      "name": "Contains Duplicate",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/contains-duplicate/"
    },
    {
      "name": "Intersection of Two Arrays",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/intersection-of-two-arrays/"
    },
    {
      "name": "Longest Consecutive Sequence",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/longest-consecutive-sequence/"
    },
    {
      "name": "Happy Number",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/happy-number/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 13,
    "frames": [
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {},
        "explanation": "A set holds each value at most once, and answers 'have I seen this?' instantly. It's a hash map that kept the keys and threw the values away.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 17,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 17,
          "bucket": 2,
          "alreadySeen": false
        },
        "explanation": "Have we seen 17? Hash it to bucket 2 and look. Only that one bucket — never the whole collection.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "added": 17,
          "size": 1
        },
        "explanation": "Not seen before, so add 17 to the set. Adding is O(1) too — same hash, same jump.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 22,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 22,
          "bucket": 2,
          "alreadySeen": false
        },
        "explanation": "Have we seen 22? Hash it to bucket 2 and look. Only that one bucket — never the whole collection.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "added": 22,
          "size": 2
        },
        "explanation": "Not seen before, so add 22 to the set. Adding is O(1) too — same hash, same jump.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 3,
            "hash": 3
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 3,
          "bucket": 3,
          "alreadySeen": false
        },
        "explanation": "Have we seen 3? Hash it to bucket 3 and look. Only that one bucket — never the whole collection.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "added": 3,
          "size": 3
        },
        "explanation": "Not seen before, so add 3 to the set. Adding is O(1) too — same hash, same jump.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 8,
            "hash": 3
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 8,
          "bucket": 3,
          "alreadySeen": false
        },
        "explanation": "Have we seen 8? Hash it to bucket 3 and look. Only that one bucket — never the whole collection.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                },
                {
                  "id": "st3-8",
                  "key": 8,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "added": 8,
          "size": 4
        },
        "explanation": "Not seen before, so add 8 to the set. Adding is O(1) too — same hash, same jump.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                },
                {
                  "id": "st3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 12,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 12,
          "bucket": 2,
          "alreadySeen": false
        },
        "explanation": "Have we seen 12? Hash it to bucket 2 and look. Only that one bucket — never the whole collection.",
        "stats": {
          "comparisons": 5,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22
                },
                {
                  "id": "st4-12",
                  "key": 12,
                  "role": "found"
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                },
                {
                  "id": "st3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "added": 12,
          "size": 5
        },
        "explanation": "Not seen before, so add 12 to the set. Adding is O(1) too — same hash, same jump.",
        "stats": {
          "comparisons": 5,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22,
                  "role": "found"
                },
                {
                  "id": "st4-12",
                  "key": 12
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                },
                {
                  "id": "st3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 22,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "checking": 22,
          "bucket": 2,
          "alreadySeen": true
        },
        "explanation": "22 hashes to bucket 2 — and 22 is already sitting there. A duplicate, found in one step. We never had to scan the other values.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "st0-17",
                  "key": 17
                },
                {
                  "id": "st1-22",
                  "key": 22,
                  "role": "found"
                },
                {
                  "id": "st4-12",
                  "key": 12
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "st2-3",
                  "key": 3
                },
                {
                  "id": "st3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 7,
        "variables": {
          "result": true,
          "looks": 6
        },
        "explanation": "Duplicate found after 6 looks. Checking every pair with nested loops would have been O(n²); this was O(n), because each \"have I seen it?\" is O(1).",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "found"
      }
    ]
  }
}