LeetCode 2278 - Percentage of Letter in String

This problem asks us to calculate the percentage of a given character, letter, in a string s, and return it as an integer rounded down to the nearest whole percent.

LeetCode Problem 2278

Difficulty: 🟢 Easy
Topics: String

Solution

Problem Understanding

This problem asks us to calculate the percentage of a given character, letter, in a string s, and return it as an integer rounded down to the nearest whole percent. Essentially, we need to determine how many times the character occurs, divide by the total number of characters, multiply by 100, and then round down.

The input s is a non-empty string containing only lowercase English letters, and letter is a single lowercase English letter. The constraints tell us that the string length is small (up to 100), so a simple counting approach is feasible.

Important edge cases include when the letter does not appear in the string (result should be 0), when the letter appears every time (result should be 100), and when the division produces a non-integer percentage (round down).

Approaches

The brute-force approach is straightforward: iterate through every character of the string, count how many times it matches letter, then compute the percentage by dividing the count by the string length and multiplying by 100. This is correct and efficient enough given the small input size, but it is simple enough to be considered optimal as well.

The key insight for the optimal solution is that we only need a single pass through the string to count occurrences. There is no need for additional data structures or complex operations. The percentage calculation can be done using integer division to automatically round down.

Approach Time Complexity Space Complexity Notes
Brute Force O(n) O(1) Iterate through string to count occurrences
Optimal O(n) O(1) Single pass with direct percentage calculation

Algorithm Walkthrough

  1. Initialize a variable count to 0 to store the number of times letter appears in s.
  2. Iterate through each character c in s.
  3. For each character, check if c == letter. If it does, increment count.
  4. After the iteration, calculate the percentage by dividing count by the total length of the string and multiplying by 100. Use integer division to round down automatically.
  5. Return the calculated percentage as the result.

Why it works: This algorithm works because it counts all occurrences of the target letter accurately and uses integer arithmetic to enforce rounding down. Since every character is inspected exactly once, and we only perform a single division at the end, the result is guaranteed to be correct.

Python Solution

class Solution:
    def percentageLetter(self, s: str, letter: str) -> int:
        count = 0
        for c in s:
            if c == letter:
                count += 1
        return (count * 100) // len(s)

The code initializes a counter and iterates through the string. Every time the character matches letter, the counter is incremented. After completing the loop, we multiply the count by 100 and use integer division by the length of the string to calculate the percentage rounded down. This directly follows the algorithm walkthrough.

Go Solution

func percentageLetter(s string, letter byte) int {
    count := 0
    for i := 0; i < len(s); i++ {
        if s[i] == letter {
            count++
        }
    }
    return (count * 100) / len(s)
}

In Go, strings are indexed by byte, so we iterate over the indices and compare each character with letter. The percentage calculation uses integer division to round down, just like in Python. Since Go does not have a class structure for this problem, we implement it as a simple function.

Worked Examples

Example 1: s = "foobar", letter = "o"

Step Character Count Comment
1 'f' 0 Not 'o'
2 'o' 1 Match
3 'o' 2 Match
4 'b' 2 Not 'o'
5 'a' 2 Not 'o'
6 'r' 2 Not 'o'

Percentage: (2 * 100) // 6 = 200 // 6 = 33

Example 2: s = "jjjj", letter = "k"

Step Character Count Comment
1 'j' 0 Not 'k'
2 'j' 0 Not 'k'
3 'j' 0 Not 'k'
4 'j' 0 Not 'k'

Percentage: (0 * 100) // 4 = 0

Complexity Analysis

Measure Complexity Explanation
Time O(n) We iterate through the string of length n exactly once
Space O(1) Only a fixed-size counter is used

Since the string length is at most 100, the algorithm is extremely efficient for all valid inputs.

Test Cases

# Provided examples
assert Solution().percentageLetter("foobar", "o") == 33  # 'o' appears 2/6
assert Solution().percentageLetter("jjjj", "k") == 0     # 'k' does not appear

# Edge cases
assert Solution().percentageLetter("a", "a") == 100      # Single character match
assert Solution().percentageLetter("a", "b") == 0        # Single character no match
assert Solution().percentageLetter("abcabcabc", "a") == 33  # Multiple letters
assert Solution().percentageLetter("zzzzzzzz", "z") == 100  # All letters match
assert Solution().percentageLetter("abcdef", "f") == 16     # Single match at end
Test Why
"foobar", "o" Normal case with partial match
"jjjj", "k" No occurrences
"a", "a" Single character match
"a", "b" Single character no match
"abcabcabc", "a" Multiple letters, repeated pattern
"zzzzzzzz", "z" All letters match
"abcdef", "f" Single match at the end

Edge Cases

One important edge case is when the string consists of only the target letter. This could potentially cause off-by-one errors in percentage calculation, but integer division handles it correctly, giving 100%.

Another edge case is when the target letter does not appear at all. A naive implementation that does not check for zero division could fail, but since we divide by the string length and not by the count, this case returns 0 correctly.

Finally, consider very short strings, such as length 1. The implementation handles this naturally by counting and performing integer division. For example, if the single character matches, the percentage is 100, and if not, it is 0. This ensures correctness for the minimum input size.