Toggle Case
Description
Given a string s, return it with the case of every letter swapped: each lowercase letter becomes uppercase and each uppercase letter becomes lowercase. Characters that aren't letters stay as they are.
Examples
Example 1
Input: s = "Hi, Bob"
Output: "hI, bOB"
Explanation: H and B become lowercase, i, o and b become capitals, and the comma and the space stay.
Example 2
Input: s = "abc"
Output: "ABC"
Explanation: Every letter is lowercase, so every one becomes a capital.
Example 3
Input: s = "123 ?!"
Output: "123 ?!"
Explanation: No letters, so nothing changes.
Example 4
Input: s = "JavaScript"
Output: "jAVAsCRIPT"
Explanation: J and S become lowercase; the rest become capitals.
Constraints
- 1 ≤ s.length ≤ 10^5
sconsists of printable ASCII characters
Editorial
Approach - Flip Each Letter
Intuition
Go through the string once. A lowercase letter becomes its capital, a capital becomes lowercase, and anything that isn't a letter is copied as it is. The capitals are 'A' to 'Z' and the lowercase letters 'a' to 'z', two separate ranges: between them in ASCII sit [, \, ], ^, _ and the backquote, which aren't letters.
Strings can't change in place in Python, Java or JavaScript, so build the answer in a list or a StringBuilder and join it once. C++ strings can change, so its version flips a copy in place.
Step-by-Step Explanation
Let's trace Example 1, s = "Hi, Bob":
- The capitals
HandBbecomehandb. - The lowercase letters
i,o,bbecomeI,O,B. - The comma and the space aren't letters, so they stay.
- Return
"hI, bOB".
Flip Each Letter — The string on top; below, the answer as it's built.
Algorithm
- For each character: if it's from
atoz, add its capital; if it's fromAtoZ, add its lowercase; otherwise add it unchanged. - Return what was built.
Code
class Solution {
public:
string toggleCase(string& s) {
string out = s;
for (char& c : out) {
if (c >= 'a' && c <= 'z') c = c - 'a' + 'A';
else if (c >= 'A' && c <= 'Z') c = c - 'A' + 'a';
} // anything else stays as it is
return out;
}
};
class Solution:
def toggleCase(self, s: str) -> str:
out = []
for c in s:
if "a" <= c <= "z":
out.append(c.upper())
elif "A" <= c <= "Z":
out.append(c.lower())
else:
out.append(c) # not a letter: unchanged
return "".join(out)
class Solution {
public String toggleCase(String s) {
StringBuilder out = new StringBuilder();
for (char c : s.toCharArray()) {
if (c >= 'a' && c <= 'z') out.append((char) (c - 'a' + 'A'));
else if (c >= 'A' && c <= 'Z') out.append((char) (c - 'A' + 'a'));
else out.append(c); // not a letter: unchanged
}
return out.toString();
}
}
var toggleCase = function(s) {
const out = [];
for (const c of s) {
if (c >= "a" && c <= "z") out.push(c.toUpperCase());
else if (c >= "A" && c <= "Z") out.push(c.toLowerCase());
else out.push(c); // not a letter: unchanged
}
return out.join("");
};
Complexity Analysis
Time Complexity: O(n)
Each character is looked at once.
Space Complexity: O(n)
The answer, built one character at a time.
Common Mistakes
Each of these looks right on a quick read, and the tests still reject it. The outputs below come from running the code.
Making everything uppercase. return s.upper()
On s = "Hi, Bob" it returns "HI, BOB"; the answer is "hI, bOB". Toggling goes both ways: capitals have to become lowercase too, so s.upper() gets every capital wrong.
Treating A to z as one range. if "A" <= c <= "z":
On s = "under_score" it returns "UNDER\u007fSCORE"; the answer is "UNDER_SCORE". In ASCII the capitals run from 65 to 90 and the lowercase letters from 97 to 122. Between them sit six characters that aren't letters, [, \, ], ^, _ and the backquote, so "A" <= c <= "z" sweeps them in and flips them into other characters.
Flipping every character. chr(ord(c) ^ 32) for c in s
On s = "a[b" it returns "A{B"; the answer is "A[B". A letter's case is one bit, 32, so ord(c) ^ 32 toggles it. But the same flip changes every other character too: [ becomes {, and a digit or a space becomes an invisible control character. Only letters may be touched.
Where This Pattern Is Taught
This problem practises building a new string from an old one, one character at a time. It's taught in Introduction to Strings.