A clear explanation of converting uppercase ASCII letters to lowercase by scanning the string once.
Problem Restatement
We are given a string s.
Return a new string after replacing every uppercase letter with the same lowercase letter.
All other characters stay unchanged.
The string consists of printable ASCII characters.
Input and Output
| Item | Meaning |
|---|---|
| Input | A string s |
| Output | The same string with uppercase letters converted to lowercase |
| Constraint | 1 <= s.length <= 100 |
| Characters | Printable ASCII characters |
The function shape is:
class Solution:
def toLowerCase(self, s: str) -> str:
...Examples
Example 1:
s = "Hello"The uppercase letter H becomes h.
Output:
"hello"Example 2:
s = "here"There are no uppercase letters.
Output:
"here"Example 3:
s = "LOVELY"Every letter is uppercase.
Output:
"lovely"First Thought: Use the Built-in Method
Python already has a method for this:
s.lower()So the shortest accepted solution is:
class Solution:
def toLowerCase(self, s: str) -> str:
return s.lower()This is correct and simple.
But this problem is often used to practice character handling, so we can also implement the conversion manually.
Key Insight
In ASCII, uppercase letters have consecutive codes:
'A' -> 65
'B' -> 66
...
'Z' -> 90Lowercase letters also have consecutive codes:
'a' -> 97
'b' -> 98
...
'z' -> 122The difference between matching uppercase and lowercase letters is always:
ord('a') - ord('A') == 32So if a character ch is between 'A' and 'Z', its lowercase version is:
chr(ord(ch) + 32)Characters outside that uppercase range should be copied unchanged.
Algorithm
Create an empty list result.
For each character ch in s:
- If
chis between'A'and'Z', convert it to lowercase by adding32to its ASCII code. - Otherwise, keep
chunchanged. - Append the resulting character to
result.
At the end, join the list into a string.
Correctness
The algorithm examines every character of s.
If a character is an uppercase ASCII letter, then it lies between 'A' and 'Z'. Adding 32 to its ASCII value gives the matching lowercase letter. Therefore the algorithm converts every uppercase letter correctly.
If a character is not an uppercase ASCII letter, the algorithm appends it unchanged. Therefore lowercase letters, digits, spaces, and punctuation are preserved.
Since every character is processed exactly once and appended in the original order, the returned string is exactly s with uppercase letters replaced by their lowercase versions.
Complexity
Let n be the length of s.
| Metric | Value | Why |
|---|---|---|
| Time | O(n) | We scan every character once |
| Space | O(n) | We build a result string of length n |
Implementation
class Solution:
def toLowerCase(self, s: str) -> str:
result = []
for ch in s:
if "A" <= ch <= "Z":
result.append(chr(ord(ch) + 32))
else:
result.append(ch)
return "".join(result)Code Explanation
We use a list because strings are immutable in Python:
result = []For each character, check whether it is uppercase ASCII:
if "A" <= ch <= "Z":If so, convert it:
result.append(chr(ord(ch) + 32))If not, keep it unchanged:
else:
result.append(ch)Finally, join all characters into the answer:
return "".join(result)Alternative: Bit Operation
ASCII uppercase and lowercase letters differ by one bit.
So another manual conversion is:
class Solution:
def toLowerCase(self, s: str) -> str:
result = []
for ch in s:
if "A" <= ch <= "Z":
result.append(chr(ord(ch) | 32))
else:
result.append(ch)
return "".join(result)This works because ord(ch) | 32 sets the lowercase bit for uppercase ASCII letters.
The range check is still important. Without it, applying | 32 to punctuation or other characters can change them incorrectly.
Testing
def test_to_lower_case():
s = Solution()
assert s.toLowerCase("Hello") == "hello"
assert s.toLowerCase("here") == "here"
assert s.toLowerCase("LOVELY") == "lovely"
assert s.toLowerCase("A1B2C3") == "a1b2c3"
assert s.toLowerCase("Python-3.12!") == "python-3.12!"
assert s.toLowerCase("already lower") == "already lower"
print("all tests passed")
test_to_lower_case()Test coverage:
| Test | Why |
|---|---|
| Mixed case | Confirms partial conversion |
| Already lowercase | Confirms unchanged letters |
| All uppercase | Confirms full conversion |
| Digits | Confirms nonletters stay unchanged |
| Punctuation | Confirms printable ASCII characters are preserved |