Repeated DNA Sequences - Complete Solution Guide
Repeated DNA Sequences is LeetCode problem 187, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
The DNA sequence is composed of a series of nucleotides abbreviated as 'A' , 'C' , 'G' , and 'T' . For example, "ACGAATTCCG" is a DNA sequence . When studying DNA , it is useful to identify repeated sequences within the DNA. Given a string s that represents a DNA sequence , return all the 10 -letter-long sequences (substrings) that occur more than once in a DNA molecule. You may return the answer in any order . Example 1: Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" Output: ["AAAAACCCCC","CCCCC
Detailed Explanation
The problem requires us to find all 10-letter-long sequences (substrings) that occur more than once in a given DNA sequence (string) consisting of characters 'A', 'C', 'G', and 'T'. The function should return a list of these repeated sequences, and the order of the sequences in the output list doesn't matter.
Solution Approach
The solution utilizes a sliding window of length 10 and a hash set to efficiently identify repeated DNA sequences. Each 10-letter sequence is converted into an integer representation using bit manipulation. The algorithm iterates through the DNA string, calculating the hash value for each 10-letter sequence. If a sequence's hash value is already present in the `seen` set, it means the sequence has been encountered before, and it's added to the `output` set. Otherwise, the sequence's hash value is added to the `seen` set. Using sets ensures that each repeated sequence is added to the result only once.
Step-by-Step Algorithm
- Step 1: Initialize variables: `L = 10` (length of sequences to find), `n` (length of the input string), `to_int` (a mapping of nucleotides to integers: A->0, C->1, G->2, T->3), `seen` (a set to store encountered sequences' hash values), `output` (a set to store the repeated sequences themselves), and `mask` (used for the rolling hash).
- Step 2: Handle the edge case where the input string's length is less than or equal to `L`. If so, return an empty list.
- Step 3: Calculate the initial hash value for the first 10-letter sequence.
- Step 4: Add the initial hash value to the `seen` set.
- Step 5: Iterate through the remaining characters of the string (from index 10 to the end). For each character:
- Step 6: Update the hash value using a rolling hash technique. This involves left-shifting the current hash value by 2 bits, applying the `mask` to keep the hash within the required bit range, and then adding the integer representation of the current character.
- Step 7: Check if the current hash value is already present in the `seen` set. If it is, add the corresponding sequence (substring) to the `output` set.
- Step 8: If the hash value is not in `seen`, add it to the `seen` set.
- Step 9: Convert the `output` set to a list and return the list of repeated DNA sequences.
Key Insights
- Insight 1: A sliding window of size 10 can be used to iterate through all possible 10-letter sequences in the DNA string.
- Insight 2: Hashing can be used to efficiently store and check for repeated sequences. Using a direct string comparison for every substring would lead to higher time complexity. A rolling hash helps update the hash value in O(1) time.
- Insight 3: Bit manipulation can be used to represent each nucleotide (A, C, G, T) with 2 bits (00, 01, 10, 11 respectively), which allows us to represent a 10-letter sequence with a 20-bit integer.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Hash Table, String, Bit Manipulation, Sliding Window, Rolling Hash, Hash Function.
Companies
Asked at: Grammarly, LinkedIn, Tesla.