Category: Easy | Concepts used: Character classification, ASCII vs Unicode representations
Problem Statement
Given a string, count how many uppercase letters and how many lowercase letters it contains.
Input : "Hello World" Output: Uppercase = 2, Lowercase = 8
Input : "12345" Output: Uppercase = 0, Lowercase = 0
Examples (with edge scenarios)
| # | Input | Uppercase | Lowercase | Why |
|---|---|---|---|---|
| 1 | "Hello World" | 2 | 8 | H, W are uppercase; rest are lowercase |
| 2 | "" | 0 | 0 | Empty string contains nothing |
| 3 | "12345!@#" | 0 | 0 | Digits/symbols are neither |
| 4 | "ABC" | 3 | 0 | All uppercase letters |
| 5 | "abc" | 0 | 3 | All lowercase letters |
โ ๏ธ Common Beginner Mistake
Mistake Impact Fix Checking only ASCII ranges ( ch >= 'A' && ch <= 'Z')Fails to detect international capital characters like รorรUse Javaโs built-in Character.isUpperCase()Assuming characters that arenโt uppercase must be lowercase Incorrectly counts spaces and digits as lowercase letters Always use an explicit else iffor lowercase checks
Before You Code: Clarify the Contract
Before choosing an algorithm, confirm how null and empty strings should behave, whether comparison is case-sensitive, and whether spaces or punctuation count. Java char values are UTF-16 code units, not always complete human-visible Unicode characters, so international text may require code points or grapheme-aware libraries.
Analogy: Sorting Mail by Envelope Size
Imagine you are sorting incoming mail. You have two target buckets: one for large manila envelopes (Uppercase) and one for small letter envelopes (Lowercase):
- You inspect each package one by one.
- If itโs a large envelope, put it in the โlargeโ bucket (
upper++). - If itโs a small envelope, put it in the โsmallโ bucket (
lower++). - If you pull out a package that is a package box, tube, or poster (numbers, spaces, punctuation), it doesnโt fit either category. You simply stack it to the side and ignore it!
Solution 1 โ Manual ASCII Range Check
This approach checks if the numeric representation of the character falls within the uppercase or lowercase ASCII block.
Intuition
Behind the scenes, every character is represented by a number. Uppercase characters sit between decimal 65 (A) and 90 (Z). Lowercase letters sit between 97 (a) and 122 (z).
public class CaseCounterManual {
public static void countCase(String str) {
if (str == null) {
System.out.println("Uppercase = 0, Lowercase = 0");
return;
}
int upper = 0, lower = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
upper++;
} else if (ch >= 'a' && ch <= 'z') {
lower++;
}
// All non-alphabetic characters are automatically skipped
}
System.out.println("Uppercase = " + upper + ", Lowercase = " + lower);
}
public static void main(String[] args) {
countCase("Hello World"); // Uppercase = 2, Lowercase = 8
countCase("12345!@#"); // Uppercase = 0, Lowercase = 0
}
}
Output:
Uppercase = 2, Lowercase = 8
Uppercase = 0, Lowercase = 0
Dry Run (str = โHi!โ)
i = 0: 'H' -> within 'A'-'Z' -> upper = 1
i = 1: 'i' -> within 'a'-'z' -> lower = 1
i = 2: '!' -> neither range -> ignored
Final Output: Uppercase = 1, Lowercase = 1
Solution 2 โ Using Character.isUpperCase() / isLowerCase() (Preferred)
This approach uses built-in helper methods which support Unicode characters.
Intuition
Rather than relying on raw English ASCII limits, we use the JVM standard methods. This makes the code shorter, more readable, and robust against international charsets.
public class CaseCounterBuiltIn {
public static void countCase(String str) {
if (str == null) {
System.out.println("Uppercase = 0, Lowercase = 0");
return;
}
int upper = 0, lower = 0;
for (char ch : str.toCharArray()) {
if (Character.isUpperCase(ch)) {
upper++;
} else if (Character.isLowerCase(ch)) {
lower++;
}
}
System.out.println("Uppercase = " + upper + ", Lowercase = " + lower);
}
public static void main(String[] args) {
countCase("Hello World"); // Uppercase = 2, Lowercase = 8
countCase("ABC"); // Uppercase = 3, Lowercase = 0
}
}
Output:
Uppercase = 2, Lowercase = 8
Uppercase = 3, Lowercase = 0
๐ Visual Flowchart
graph TD
Start["Input String S"] --> Empty{"S is null or empty?"}
Empty -->|Yes| End["Print: Upper=0, Lower=0"]
Empty -->|No| Init["Initialize upper=0, lower=0"]
Init --> Loop{"i < S.length()?"}
Loop -->|Yes| Fetch["ch = S.charAt(i)"]
Fetch --> IsUpper{"Character.isUpperCase(ch)?"}
IsUpper -->|Yes| IncUpper["upper++"]
IsUpper -->|No| IsLower{"Character.isLowerCase(ch)?"}
IsLower -->|Yes| IncLower["lower++"]
IsLower -->|No| IncLoop["i++"]
IncUpper --> IncLoop
IncLower --> IncLoop
IncLoop --> Loop
Loop -->|No| Print["Print: upper, lower"]
Print --> End
Interviewer Insights
This is a typical QA automation question assessing basic logic paths.
Follow-up questions you might get:
- โWhat is the main advantage of Solution 2 over Solution 1?โ โ Solution 1 only works for basic Latin/English characters. Solution 2 evaluates Unicode properties, so it correctly counts uppercase/lowercase characters from languages such as Spanish, French, German, or Cyrillic characters.
- โWhy is toCharArray() used in Solution 2?โ โ
toCharArray()makes the loop syntax cleaner by returning a raw array of characters. Note that this creates a temporary char array copy in memory, so for memory-critical scenarios,str.charAt(i)inside a standard index loop is slightly more efficient.
Quick Recap
| Approach | Unicode Support? | Time Complexity | Space Complexity | Interview Signal |
|---|---|---|---|---|
| Manual ASCII Check | No (English only) | (O(N)) | (O(1)) | Demonstrates low-level ASCII conversion understanding |
Character Helpers | Yes | (O(N)) | (O(1)) | Clean, robust, internationalized, standard production code |
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed