Start learning free

LESSON 289 OF 410 · BACKTRACKING

Generate Binary Strings With K Ones in JavaScript (Time Complexity: O(2^N))

Practice O(2^n) Read the full explanation

Given two non-negative integers N and K, return the binary strings of length N with exactly K ones.

Example:

Input: N = 4, K = 2
Output: [
    "0011",
    "0101",
    "0110",
    "1001",
    "1010",
    "1100"
]
Notes: K <= N <= 20
STEP 1 OF 10
    Ctrl + Enter to check

    JAVASCRIPT · BACKTRACKING

    Generate Binary Strings With K Ones in JavaScript, explained

    Understanding the Problem

    The core challenge of this problem is to generate all possible binary strings of length N that contain exactly K ones. This problem is significant in various fields such as combinatorics, coding theory, and computer science. A common application is in generating test cases or configurations where a specific number of features (represented by ones) need to be active.

    Potential pitfalls include generating strings with more or fewer than K ones or not considering all possible combinations.

    Approach

    To solve this problem, we can use a recursive backtracking approach. The idea is to build the binary string one bit at a time, ensuring that we place exactly K ones in the string.

    1. **Naive Solution**: Generate all possible binary strings of length N and filter out those with exactly K ones. This approach is not optimal because it generates many unnecessary strings.

    2. **Optimized Solution**: Use backtracking to build the string and ensure that we only generate valid strings with exactly K ones.

    Optimized Approach

    1. Start with an empty string and a count of ones set to 0.

    2. At each step, add either '0' or '1' to the string.

    3. If adding '1', increment the count of ones.

    4. If the count of ones exceeds K, backtrack.

    5. If the length of the string reaches N and the count of ones is exactly K, add the string to the result.

    Algorithm

    Here is a step-by-step breakdown of the backtracking algorithm:

    1. Initialize an empty result array to store the valid binary strings.
    2. Define a recursive function that takes the current string, the count of ones, and the remaining length as parameters.
    3. In the recursive function, if the remaining length is 0, check if the count of ones is K. If so, add the string to the result.
    4. If the remaining length is not 0, recursively call the function twice: once adding '0' to the string and once adding '1' (if the count of ones is less than K).
    5. Return the result array.

    Code Implementation

    /**
     * Generate all binary strings of length N with exactly K ones.
     * @param {number} N - Length of the binary strings.
     * @param {number} K - Number of ones in the binary strings.
     * @return {string[]} - Array of binary strings.
     */
    function generateBinaryStrings(N, K) {
        const result = [];
    
        // Helper function for backtracking
        function backtrack(currentString, onesCount, remainingLength) {
            // Base case: if the remaining length is 0
            if (remainingLength === 0) {
                // Check if the current string has exactly K ones
                if (onesCount === K) {
                    result.push(currentString);
                }
                return;
            }
    
            // Add '0' to the current string and recurse
            backtrack(currentString + '0', onesCount, remainingLength - 1);
    
            // Add '1' to the current string and recurse if onesCount < K
            if (onesCount < K) {
                backtrack(currentString + '1', onesCount + 1, remainingLength - 1);
            }
        }
    
        // Start the backtracking process
        backtrack('', 0, N);
    
        return result;
    }
    
    // Example usage:
    const N = 4;
    const K = 2;
    console.log(generateBinaryStrings(N, K)); // Output: ["1100", "1010", "1001", "0110", "0101", "0011"]
    

    Complexity Analysis

    The time complexity of this approach is O(2^N) because in the worst case, we explore all possible binary strings of length N. The space complexity is O(N) due to the recursion stack and the storage of the result.

    Edge Cases

    Potential edge cases include:

    • N = 0, K = 0: The output should be an empty string [""]
    • K = 0: The output should be a string of N zeros.
    • K = N: The output should be a string of N ones.

    Testing for these edge cases ensures the robustness of the solution.

    Testing

    To test the solution comprehensively, consider the following test cases:

    • Simple cases: N = 1, K = 0; N = 1, K = 1
    • Edge cases: N = 0, K = 0; N = 5, K = 0; N = 5, K = 5
    • General cases: N = 4, K = 2; N = 6, K = 3

    Using a testing framework like Jest can help automate and validate these test cases.

    Thinking and Problem-Solving Tips

    When approaching such problems:

    • Break down the problem into smaller sub-problems.
    • Consider using recursive approaches for combinatorial problems.
    • Think about the constraints and how they can simplify the problem.
    • Practice similar problems to improve problem-solving skills.

    Conclusion

    Generating binary strings with exactly K ones is a classic combinatorial problem that can be efficiently solved using backtracking. Understanding and solving such problems enhances algorithmic thinking and problem-solving skills.

    Practice and explore further to master these concepts.

    Additional Resources

    Keep going with JavaScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free