class Solution:
def licenseKeyFormatting(self, S: str, K: int) -> str:
# Remove dashes and convert to uppercase
S = S.replace('-', '').upper()
size = len(S)
# Find the size of the first group
first_group = size % K
groups = []
if first_group:
groups.append(S[:first_group])
# Process the rest of the groups
for i in range(first_group, size, K):
groups.append(S[i:i+K])
return '-'.join(groups)
class Solution {
public:
string licenseKeyFormatting(string S, int K) {
string s;
// Remove dashes and convert to uppercase
for (char c : S) {
if (c != '-') s += toupper(c);
}
int size = s.size();
string res;
int first_group = size % K;
int i = 0;
if (first_group) {
res += s.substr(0, first_group);
i = first_group;
}
while (i < size) {
if (!res.empty()) res += '-';
res += s.substr(i, K);
i += K;
}
return res;
}
};
class Solution {
public String licenseKeyFormatting(String S, int K) {
S = S.replace("-", "").toUpperCase();
int size = S.length();
int firstGroup = size % K;
StringBuilder sb = new StringBuilder();
if (firstGroup != 0) {
sb.append(S.substring(0, firstGroup));
}
for (int i = firstGroup; i < size; i += K) {
if (sb.length() > 0) sb.append("-");
sb.append(S.substring(i, i + K));
}
return sb.toString();
}
}
var licenseKeyFormatting = function(S, K) {
S = S.replace(/-/g, '').toUpperCase();
let size = S.length;
let firstGroup = size % K;
let groups = [];
if (firstGroup !== 0) {
groups.push(S.slice(0, firstGroup));
}
for (let i = firstGroup; i < size; i += K) {
groups.push(S.slice(i, i + K));
}
return groups.join('-');
};
Given a string S
representing a license key and an integer K
, reformat the string so that:
K
, except possibly the first group which may be shorter but must contain at least one character.'-'
.S
are ignored and should not appear in the output unless as group separators.The solution must return the reformatted license key as a string.
At first glance, the problem seems to require a lot of string manipulation. One could try to process the string while keeping track of dashes and group sizes, but that quickly becomes messy. Instead, a better approach is to first remove all dashes and convert all letters to uppercase, so we only have a clean string to work with.
Once we have the cleaned string, the next challenge is to split it into groups of size K
. The first group might be shorter, but all groups after that must be exactly of size K
. By calculating the length of the first group, we can easily iterate over the rest of the string in steps of K
.
This eliminates the need for complex state tracking and allows us to build the result group by group, joining them with dashes at the end.
S
. This gives us only the alphanumeric characters.K
, the first group will be shorter (specifically, len % K
characters).K
.This approach is efficient because it only processes the string a constant number of times, and avoids unnecessary complexity by treating the string as a sequence of characters rather than dealing with dashes as they appear in the original input.
Let's consider the input S = "2-5g-3-J"
and K = 2
.
"25g3J"
."25G3J"
.5 % 2 = 1
(so first group has 1 character)."2"
. Remaining: "5G3J"
."5G"
. Next group: "3J"
."2-5G-3J"
.
The output is "2-5G-3J"
.
Brute-force approach: If we tried to process the string character by character, inserting dashes as needed, the complexity could still be O(N), but the implementation would be more complicated and error-prone.
Optimized approach (as described above):
S
. We process each character a constant number of times (removing dashes, converting to uppercase, grouping).The key insight for this problem is to simplify the input by removing dashes and converting to uppercase first, which makes grouping straightforward. By calculating the size of the first group, we can efficiently split the string and join the groups with dashes. This approach is both easy to understand and efficient, making it an elegant solution to the License Key Formatting problem.