Hashing an unordered sequence of small integers
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Hashing is a fundamental concept in computer science used to uniquely represent objects, perform efficient data retrieval, and manage sets or dictionaries. When dealing with unordered sequences of small integers, specialized hashing techniques can be optimized to improve performance and reduce collisions. This article explores various methods for hashing such sequences, explains the technical tradeoffs, and provides concrete examples.
Basics of Hashing
Hashing transforms an input (or key) into a fixed-size hash code through a hash function. A good hash function must satisfy two properties:
- Determinism: The same input always produces the same hash value.
- Uniformity: Different inputs distribute evenly over the hash space to minimize collisions.
Hash collisions occur when different inputs produce the same hash value, leading to degraded performance in hash-based data structures.
The Core Challenge: Order Independence
When hashing an unordered sequence (a multiset), the hash function must be commutative. Sequences containing the same elements in different orders must produce the same hash value. For example, {3, 1, 2} and {2, 3, 1} must hash identically.
This rules out standard approaches like hashing concatenated elements or using position-dependent calculations. Instead, we need operations that are inherently order-independent.
Techniques for Order-Independent Hashing
1. XOR-Based Hashing
XOR each element's individual hash together. Since XOR is both commutative and associative, the result is order-independent:
Pros: Simple and fast ( time).
Cons: XOR has a critical weakness. Duplicate elements cancel out because . The multisets {1, 1, 2} and {2} would hash identically. This makes XOR unsuitable when duplicates matter.
2. Summation-Based Hashing
Sum the individual element hashes:
This handles duplicates correctly since in general. However, it is more prone to accidental collisions compared to multiplicative approaches, since many different multisets can produce the same sum.
3. Prime Product Hashing
Assign each possible integer value a distinct prime number and compute the product:
where maps integer to the -th prime number. By the fundamental theorem of arithmetic, the product uniquely identifies the multiset (up to overflow). For small integers, you can precompute a prime table:
Pros: Collision-free for multisets (within overflow limits), handles duplicates correctly.
Cons: Products grow quickly. For large sequences, you need modular arithmetic, which reintroduces collision possibility.
4. Sorted Canonical Form
Sort the sequence and then apply any standard hash function to the sorted result. Sorting is the simplest conceptual approach:
Pros: Straightforward, leverages existing hash functions.
Cons: Sorting adds overhead. For small integer ranges, counting sort reduces this to where is the range of values.
5. Counting Vector Hashing
Since the integers are small, represent the multiset as a frequency vector and hash the vector:
This runs in time and space, where is the range of integer values. It is highly efficient when is small.
Comparison of Methods
| Method | Time Complexity | Handles Duplicates | Collision Risk |
| XOR | No | High (duplicates cancel) | |
| Summation | Yes | Moderate | |
| Prime Product | Yes | None (within limits) | |
| Sorted Canonical | Yes | Low | |
| Counting Vector | Yes | Low |
Practical Considerations
- Hash quality: For practical use, combine a commutative aggregation (sum or product) with a strong per-element hash function (like MurmurHash or xxHash) to reduce collision probability.
- Overflow handling: With prime products, use modular arithmetic ( for a large prime ) to keep values bounded.
- Small integer range: When the range of possible values is small, the counting vector approach is often the most practical. It avoids sorting overhead and naturally handles duplicates.
Applications
- Data deduplication: Identify identical datasets regardless of element ordering.
- Database query optimization: Hash-based grouping of multiset-valued columns.
- Game state hashing: Board positions where piece order does not matter (e.g., Zobrist hashing in chess uses XOR for incremental updates).
- Chemical compound identification: Molecular formulas are essentially multisets of atoms.
Summary
Hashing unordered sequences of small integers requires order-independent hash functions. For most practical purposes, prime product hashing or counting vector hashing provides the best combination of correctness and efficiency. XOR is fast but fails with duplicates. Summation works but has higher collision risk. The canonical sort approach is simple but adds sorting overhead. Choose the method based on your constraints around duplicate handling, integer range, and performance requirements.
Related reading
- HashMap get/put complexity
- Hashtable with doubly linked lists?
- Have you used a traveling salesman algorithm to solve a problem?
- Have/Want List Matching Algorithm
- Hashing of pointer values
- HashMap - contains and get methods should not be used together
- HDBSCAN difference between parameters
- HDR image creating algorithm

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.