Take K of Each Character From Left and Right

Updated on 15 July, 2025
Take K of Each Character From Left and Right header image

Problem Statement

The task is to determine the minimum time, measured in consecutive minutes, needed to extract at least k instances of each character ('a', 'b', and 'c') from a given string s, which is exclusively composed of these three characters. In each minute, you can remove either the leftmost or rightmost character from the string. If it's not feasible to obtain at least k instances of each character based on the makeup of s, the function should return -1. This task combines elements of string manipulation and optimization to achieve the desired counts in the minimum time possible.

Examples

Example 1

Input:

s = "aabaaaacaabc", k = 2

Output:

8

Explanation:

Take three characters from the left of s. You now have two 'a' characters, and one 'b' character.
Take five characters from the right of s. You now have four 'a' characters, two 'b' characters, and two 'c' characters.
A total of 3 + 5 = 8 minutes is needed.
It can be proven that 8 is the minimum number of minutes needed.

Example 2

Input:

s = "a", k = 1

Output:

-1

Explanation:

It is not possible to take one 'b' or 'c' so return -1.

Constraints

  • 1 <= s.length <= 105
  • s consists of only the letters 'a', 'b', and 'c'.
  • 0 <= k <= s.length

Approach and Intuition

The essence of solving this problem lies in the efficient evaluation of how quickly each character can be accumulated by removing characters from either end of the string. Here's a high-level breakdown of how this can be approached:

  1. If k is 0, the minimum minutes required would be 0 since we do not need any characters.

  2. First, check if the string contains at least k of each character ('a', 'b', and 'c'). If not, directly return -1 as it’s impossible to gather the required counts.

  3. Utilizing a two-pointer technique (or similarly, a sliding window approach) can be beneficial:

    • Initiate with one pointer at the start and another at the end of the string.
    • Gradually move the pointers inward, counting how many of each character is needed from the respective ends of the string to accumulate at least k characters.
    • Calculate the minutes needed by summing up the movements of both pointers once the condition of at least k characters of each type is satisfied on both sides.
  4. Since both ends of the string can be used to gather the required characters, all combinations of left and right extractions need to be evaluated to ensure the minimum time is found:

    • Count characters from the left until all characters are at least k, then count how many from the right are needed to top up to at least k for each character.
    • Conversely, start the same process by first counting from the right.
  5. Throughout this evaluation, continually track and update the minimum time required to achieve at least k of each character.

This problem is an interesting use case of the two-pointer technique, augmented by the need to explicitly manage counts of multiple character types and dynamically adjust extraction strategies based on the evolving state of the strings' ends. This combination makes it an intriguing problem that blends string manipulation with algorithmic strategy in optimization under constraints.

Solutions

  • C++
cpp
class Solution {
public:
    int getMinSplit(string str, int k) {
        vector<int> freq(3, 0);
        int length = str.size();
    
        for (char ch : str) {
            freq[ch - 'a']++;
        }
    
        for (int index = 0; index < 3; index++) {
            if (freq[index] < k) return -1;
        }
    
        vector<int> currentWindow(3, 0);
        int start = 0, largestWindow = 0;
    
        for (int end = 0; end < length; end++) {
            currentWindow[str[end] - 'a']++;
    
            while (start <= end &&
                (freq[0] - currentWindow[0] < k || freq[1] - currentWindow[1] < k ||
                freq[2] - currentWindow[2] < k)) {
                currentWindow[str[start] - 'a']--;
                start++;
            }
    
            largestWindow = max(largestWindow, end - start + 1);
        }
    
        return length - largestWindow;
    }
};

The given C++ solution involves a problem where one aims to extract characters from a string to ensure each character appears at least 'k' times at the beginning and end of the string. The solution checks if this is viable for a three-character alphabet (considered 'a', 'b' and 'c').

Here's an overview of the solution's logic:

  • Initialize a frequency array to count the occurrence of each character ('a', 'b', 'c') in the entire string.
  • Check if any character appears fewer than 'k' times. If so, return '-1' since such a split isn't feasible.
  • Employ a sliding window technique to determine the largest possible segment where characters outside this window can still form valid 'k' groups at both ends of the original string.
  • The function then returns the minimum length of string to split, which is the total length minus the largest valid window size.

Key considerations include:

  • The use of a frequency count to ensure each character's minimum presence.
  • Optimization via a sliding window to find the maximum segment fulfilling the 'at least k occurrences' end condition.
  • This method ensures efficiency, making it suitable for scenarios where quick adjustment and checks over string segments are necessary.
  • Java
java
class Solution {
    
    public int checkSubstring(String str, int required) {
        int[] charCount = new int[3];
        int length = str.length();
    
        // Count each character in string
        for (char ch : str.toCharArray()) {
            charCount[ch - 'a']++;
        }
    
        // Validate enough characters presence
        for (int i = 0; i < 3; i++) {
            if (charCount[i] < required) return -1;
        }
    
        int[] freq = new int[3];
        int start = 0, longest = 0;
    
        // Calculating the optimal window size
        for (int end = 0; end < length; end++) {
            freq[str.charAt(end) - 'a']++;
    
            // Adjust window if it invalidates the condition
            while (
                start <= end &&
                (charCount[0] - freq[0] < required ||
                    charCount[1] - freq[1] < required ||
                    charCount[2] - freq[2] < required)
            ) {
                freq[str.charAt(start) - 'a']--;
                start++;
            }
    
            longest = Math.max(longest, end - start + 1);
        }
    
        return length - longest;
    }
}

To tackle the problem of finding the optimal window size when taking k of each character from both the left and right in a string, this Java solution applies a sliding window technique to ensure each character 'a', 'b', and 'c' meets a specified minimum count required across the string.

The process can be outlined as follows:

  1. Initialize a charCount array to store counts of each character in the input string.
  2. Traverse the entire string to populate the charCount with the respective counts of 'a', 'b', and 'c'.
  3. Check if any character count in charCount is less than the required count. If so, return -1 indicating it's not possible to create such substring.
  4. Define another freq array to count characters within the current sliding window.
  5. Initialize two pointers, start and end, representing the window's boundaries.
  6. Extend the window by incrementing the end pointer and updating the freq array.
  7. If the window invalidates the condition (i.e., taking out characters from the window would lead anything to fall below the required count), adjust the window's start by incrementing the start pointer and updating the freq array.
  8. Continuously calculate and update the size of the longest substring that meets the requirement.
  9. Finally, the method returns the result of length - longest, where longest is the maximum valid substring length, and length is the total length of the input string.

This implementation efficiently computes the minimal adjustments needed to the string by using the sliding window to track the viable substring directly, ensuring optimal performance.

  • Python
python
class Solution:
    def longestValidSubstring(self, input_string: str, min_count: int) -> int:
        frequency = [0] * 3
        length = len(input_string)
    
        # Count total frequency of each character
        for char in input_string:
            frequency[ord(char) - ord("a")] += 1
    
        # Check if enough characters are present
        for index in range(3):
            if frequency[index] < min_count:
                return -1
    
        current_window = [0] * 3
        start_index, max_length = 0, 0
    
        # Determine the maximum valid substring length
        for end_index in range(length):
            current_window[ord(input_string[end_index]) - ord("a")] += 1
    
            # Adjust the window size
            while start_index <= end_index and (
                frequency[0] - current_window[0] < min_count
                or frequency[1] - current_window[1] < min_count
                or frequency[2] - current_window[2] < min_count
            ):
                current_window[ord(input_string[start_index]) - ord("a")] -= 1
                start_index += 1
    
            max_length = max(max_length, end_index - start_index + 1)
    
        return length - max_length

The code provided defines a method to determine and return the length of the longest valid substring composed of a minimum count of each character from the string input_string. The method longestValidSubstring calculates the length of this substring following these steps:

  1. Initialize a fixed frequency list to store the count of the first three characters 'a', 'b', and 'c' in the string, setting their initial values to zero.

  2. Count the total frequency of each character 'a', 'b', and 'c' in the string input_string.

  3. Check if all these characters meet the minimum required count (min_count). If any of them does not meet this criterion, the function returns -1, signaling that it's not possible to form a substring that meets the requirements.

  4. Use a two-pointer technique to traverse the string and keep track of the number of characters between two indices (start_index and end_index). This methodology helps to dynamically adjust the size of the substring being considered according to the specified conditions.

  5. Maintain a sliding window mechanism using current_window array to record the frequency of the characters within the current window defined by start_index and end_index.

  6. Continuously update the size of the window: shrink the window from the left side if the condition of minimum count is violated when considering the remainder of the string outside the current window.

  7. Update the maximum length of valid substring during this traversal.

  8. After fully processing the string, compute the adjusted maximum substring length ensuring that enough characters remain in the non-selected portion of the string.

  9. Return the length of the initial total string minus the length of the maximum valid substring, which represents the length of the longest valid substring that can be formed under the given conditions.

This method helps in identifying the optimal size of a substring which has a balanced distribution of specified characters, aligning with the defined rules for character count, thereby fulfilling the input constraints effectively.

Comments

No comments yet.