Strong Password Checker

Compute the minimum edits (insert, delete, replace) to make a password "strong" — careful case analysis around triplet runs.

Hard
Time O(n) Space O(1)
LeetCode
10 min read
greedy string

Problem#

A strong password (1) has length 6–20, (2) contains at least one lowercase, one uppercase, one digit, (3) has no three consecutive identical characters. Return the minimum number of single-char operations (insert, delete, replace) to make password strong.

Examples#

  • "a"5
  • "aA1"3
  • "1337C0d3"0

Hints#

Hint 1
Three independent constraints. Replacements can fix triplet runs AND missing character types simultaneously. Allocate carefully when length is wrong.

Approach#

Counts of missing categories (1–3). Find every run of ≥3 identical characters; each run of length L needs L / 3 replacements to break.

Cases:

  • length < 6: ops = max(missing, 6 - n). Inserts can fix missing too.
  • length 6..20: ops = max(missing, replacementsNeeded).
  • length > 20: must delete n - 20. Use deletions strategically on length-3k+0/1/2 runs to also reduce replacement needs, then ops = deletions + max(missing, residualReplacements).

Solution#

Strong Password Checker
class Solution {
public:
int strongPasswordChecker(string s) {
int n = s.size();
bool hasLow = false, hasUp = false, hasDig = false;
for (char c : s) {
if (islower(c)) hasLow = true;
else if (isupper(c)) hasUp = true;
else if (isdigit(c)) hasDig = true;
}
int missing = (!hasLow) + (!hasUp) + (!hasDig);
vector<int> runs;
for (int i = 0; i < n; ) {
int j = i;
while (j < n && s[j] == s[i]) ++j;
if (j - i >= 3) runs.push_back(j - i);
i = j;
}
if (n < 6) {
return max(missing, 6 - n);
}
if (n <= 20) {
int replacements = 0;
for (int r : runs) replacements += r / 3;
return max(missing, replacements);
}
int over = n - 20;
int deletions = over;
// Use deletions to optimally reduce replacement counts.
for (int k = 1; k <= 2 && over > 0; ++k) {
for (auto& r : runs) {
if (r >= 3 && r % 3 == k - 1 && over > 0) {
int use = min(over, k);
r -= use; over -= use;
}
}
}
for (auto& r : runs) {
if (r >= 3 && over > 0) {
int use = min(over, r - 2);
r -= use; over -= use;
}
}
int replacements = 0;
for (int r : runs) replacements += r / 3;
return deletions + max(missing, replacements);
}
};

Editorial#

The trick for length > 20 is that deletions help with replacement budget too — but only if applied to runs of the right length parity. A length-3k+0 run benefits most after one deletion (drops floor(L/3) by 1); 3k+1 needs two; 3k+2 needs three. Greedily prefer the cheapest reductions.

Complexity#

  • Time: O(n).
  • Space: O(n).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.