Sliding Window Technique - Part 2

Crossing the 650 problems solved milestone today (weekends in covid-filled era are great for practicing algorithms)




1461. Check If a String Contains All Binary Codes of Size K
Medium

Given a binary string s and an integer k.

Return True if any binary code of length k is a substring of s. Otherwise, return False.

 

Example 1:

Input: s = "00110110", k = 2
Output: true
Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They can be all found as substrings at indicies 0, 1, 3 and 2 respectively.

Example 2:

Input: s = "00110", k = 2
Output: true

Example 3:

Input: s = "0110", k = 1
Output: true
Explanation: The binary codes of length 1 are "0" and "1", it is clear that both exist as a substring. 

Example 4:

Input: s = "0110", k = 2
Output: false
Explanation: The binary code "00" is of length 2 and doesn't exist in the array.

Example 5:

Input: s = "0000000001011100", k = 4
Output: false

 

Constraints:

  • 1 <= s.length <= 5 * 10^5
  • s consists of 0's and 1's only.
  • 1 <= k <= 20
Accepted
4,299
Submissions
12,166

At first it looks a little daunting - generate all the 2^k possibilities and look each one up on the string of len |s|? That would bring the total execution time to 2^k * |s|, which would be in the worst case 2^20 * 5 * 10^5, or this: 524,288,000,000. You don't want that.
Instead, use the Sliding Window technique as shown in a previous post: as you traverse the string, for each window of size k, take that sub-string and insert into a hash table. At the end, if the hash table contains 2^k entries, you should return true (false otherwise). Brings the complexity down to |s|, much more reasonable. Code is below, cheers, ACC.


public class Solution
{
    public bool HasAllCodes(string s, int k)
    {
        if (String.IsNullOrEmpty(s)) return false;

        Hashtable code = new Hashtable();
        int target = (int)Math.Pow(2, k);

        string c = "";
        for (int i = 0; i < s.Length; i++)
        {
            c += s[i].ToString();

            if (i >= k)
            {
                c = c.Substring(1);
            }

            if (c.Length == k)
            {
                if (!code.ContainsKey(c))
                {
                    code.Add(c, true);
                    if (code.Count == target) return true;
                }
            }
        }

        return code.Count == target;
    }
}

Comments

  1. Changing from Hashtable to HashSet and removing the if condition (if(!code.ContainsKey(c)) improved the runtime by 12% and reduced the memory consumption a little :)

    ReplyDelete

Post a Comment

Popular posts from this blog

Golang vs. C#: performance characteristics (simple case study)

Claude vs ChatGPT: A Coder's Perspective on LLM Performance

ProjectEuler Problem 719 (some hints, but no spoilers)