Skip to main content

Toggle Case

EasyProblem

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
  • s consists 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":

  1. The capitals H and B become h and b.
  2. The lowercase letters i, o, b become I, O, B.
  3. The comma and the space aren't letters, so they stay.
  4. Return "hI, bOB".

Flip Each Letter — The string on top; below, the answer as it's built.

Algorithm

  1. For each character: if it's from a to z, add its capital; if it's from A to Z, add its lowercase; otherwise add it unchanged.
  2. 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.