{x}
blog image

Divide a String Into Groups of Size k

A string s can be partitioned into groups of size k using the following procedure:

  • The first group consists of the first k characters of the string, the second group consists of the next k characters of the string, and so on. Each character can be a part of exactly one group.
  • For the last group, if the string does not have k characters remaining, a character fill is used to complete the group.

Note that the partition is done so that after removing the fill character from the last group (if it exists) and concatenating all the groups in order, the resultant string should be s.

Given the string s, the size of each group k and the character fill, return a string array denoting the composition of every group s has been divided into, using the above procedure.

 

Example 1:

Input: s = "abcdefghi", k = 3, fill = "x"
Output: ["abc","def","ghi"]
Explanation:
The first 3 characters "abc" form the first group.
The next 3 characters "def" form the second group.
The last 3 characters "ghi" form the third group.
Since all groups can be completely filled by characters from the string, we do not need to use fill.
Thus, the groups formed are "abc", "def", and "ghi".

Example 2:

Input: s = "abcdefghij", k = 3, fill = "x"
Output: ["abc","def","ghi","jxx"]
Explanation:
Similar to the previous example, we are forming the first three groups "abc", "def", and "ghi".
For the last group, we can only use the character 'j' from the string. To complete this group, we add 'x' twice.
Thus, the 4 groups formed are "abc", "def", "ghi", and "jxx".

 

Constraints:

  • 1 <= s.length <= 100
  • s consists of lowercase English letters only.
  • 1 <= k <= 100
  • fill is a lowercase English letter.

Solution Explanation for Dividing a String into Groups of Size k

This problem involves partitioning a string s into groups of size k. If the string's length isn't a multiple of k, we pad the last group with a specified character fill to make it length k.

Approach

The most efficient way to solve this is through direct simulation. We iterate through the string in steps of k, extracting substrings of length k. For the last group, if its length is less than k, we pad it with the fill character until it reaches length k.

Time and Space Complexity Analysis

  • Time Complexity: O(n), where n is the length of the string s. This is because we iterate through the string once to create the groups. The padding operation in the last group also takes linear time in the worst case (when the last group is almost empty).

  • Space Complexity: O(n) in the worst case. The space used is primarily for storing the resulting array of strings. In the worst-case scenario where k=1, the output array will have n strings, each of length 1.

Code Implementation in Multiple Languages

The following code snippets demonstrate the solution in various programming languages. The core logic remains the same across all implementations: iterative substring extraction with padding for the last group.

Python

class Solution:
    def divideString(self, s: str, k: int, fill: str) -> List[str]:
        result = []
        for i in range(0, len(s), k):
            group = s[i:i+k]
            group = group.ljust(k, fill) # Pad with fill character if needed
            result.append(group)
        return result
 

Java

class Solution {
    public String[] divideString(String s, int k, char fill) {
        List<String> result = new ArrayList<>();
        for (int i = 0; i < s.length(); i += k) {
            String group = s.substring(i, Math.min(i + k, s.length()));
            group = String.format("%-" + k + "s", group).replace(' ', fill); //Pad with fill character
            result.add(group);
        }
        return result.toArray(new String[0]);
    }
}

C++

#include <string>
#include <vector>
#include <algorithm>
 
class Solution {
public:
    std::vector<std::string> divideString(std::string s, int k, char fill) {
        std::vector<std::string> result;
        for (int i = 0; i < s.length(); i += k) {
            std::string group = s.substr(i, std::min((int)s.length() - i, k));
            group.resize(k, fill); //Resize and fill with fill character
            result.push_back(group);
        }
        return result;
    }
};

JavaScript

/**
 * @param {string} s
 * @param {number} k
 * @param {string} fill
 * @return {string[]}
 */
var divideString = function(s, k, fill) {
    let result = [];
    for (let i = 0; i < s.length; i += k) {
        let group = s.substring(i, Math.min(i + k, s.length));
        group = group.padEnd(k, fill); //Pad with fill character
        result.push(group);
    }
    return result;
};

These implementations all follow the same core algorithm, making them efficient and easy to understand. The choice of language depends on the specific project requirements and programmer preference. The time and space complexities remain consistent across all implementations.