EN VI

Arrays - Find the number of different letters in a String given conditions; lowercase of the letter(s) cannot be ahead of the uppercase letters?

2024-03-11 02:00:04
How to Arrays - Find the number of different letters in a String given conditions; lowercase of the letter(s) cannot be ahead of the uppercase letters

You are given a string letters made of N English letters. Count the number of different letters that appear in both uppercase and lowercase where all lowercase occurrences of the given letter appear before any uppercase occurrence.

For example, for letters = "aaAbcCABBc" the answer is 2. The condition is met for letters 'a' and 'b', but not for 'c'.

Write a function:

function solution(letters);

that, given a string letters, returns the number of different letters fulfilling the conditions above.

Examples:

  1. Given letters "aaAbcCABBc", the function should return 2, as explained above.

  2. Given letters "xyzXYZabcABC", the function should return 6.

  3. Given letters "ABCabcAefG", the function should return 0.

Write an efficient algorithm for the following assumptions:

N is an integer within the range [1..100,000);

string letters is made only of letters (a-z and/or A-Z).

I wrote the following code but the third edge case kept of failing. It returned 1 instead of zero.

Here are the three test cases:
aaAbcCABBc // Output: 2
xyzXYZabcABC // Output: 6
ABCabcAefG // Output: 0

func ssolution(_ letters: String) -> Int {
    var seenLowercase = Set<Character>() // Stores seen lowercase letters
    var count = 0

    for (index, char) in letters.enumerated() {
        let lowercaseChar = char.lowercased().first!

        if char.isLowercase {
            // If lowercase, check if already seen uppercase
            if seenLowercase.contains(lowercaseChar) {
                continue
            } else {
                // Track all seen lowercase letters, even for the first encounter
                seenLowercase.insert(lowercaseChar)
            }
        } else {
            // If uppercase, check if corresponding lowercase exists after its position
            let restOfArray = letters.suffix(from: letters.index(letters.startIndex, offsetBy: index + 1))

            if !restOfArray.contains(lowercaseChar) {
                count += 1 // Valid case, increment count
                seenLowercase.remove(lowercaseChar) // Remove lowercase as seen
                continue
            } else if restOfArray.contains(lowercaseChar) {
                continue
            }
        }
        print(seenLowercase)
    }

    return count
}

// Test cases
print(ssolution("aaAbcCABBc"))  // Output: 2
print(ssolution("xyzXYZabcABC")) // Output: 6
print(ssolution("ABCabcAefG"))   // Output: 0


func ssolution(_ letters: String) -> Int {
    var seenLowercase = Set<Character>() // Stores seen lowercase letters
    var count = 0

    for (index, char) in letters.enumerated() {
        let lowercaseChar = char.lowercased().first!

        if char.isLowercase {
            let restOfArray = letters.prefix(upTo: letters.index(letters.startIndex, offsetBy: index))


            if restOfArray.contains(char.uppercased()) {
                print(seenLowercase)
                continue
            } else {
                seenLowercase.insert(lowercaseChar)
                print(seenLowercase)
                continue
            }


        } else if char.isUppercase {
            // If uppercase, check if corresponding lowercase exists after its position
            let restOfArray = letters.suffix(from: letters.index(letters.startIndex, offsetBy: index + 1))

            if !restOfArray.contains(lowercaseChar) {

                if seenLowercase.contains(char) {
                    print(seenLowercase)
                    continue
                } else if !seenLowercase.contains(char){
                    seenLowercase.remove(lowercaseChar)

                    count += 1 // Valid case, increment count

                    print(count)
                    print(seenLowercase)
                    continue
                }

            } else if restOfArray.contains(lowercaseChar) {
                print(count)
                continue
            }
        }
        print(seenLowercase)
    }

    return count
}

Solution:

What I did was to keep track of any uppercase letters that was before their lowercase counterpart in a special collection so I could check this as part of each characters validation.

My solution

func solution(_ letters: String) -> Int {
    var result = Set<Character>()
    var disqualified = Set<Character>()
    letters.indices.forEach { index in
        let char = letters[index]

        if char.isUppercase {
            let lowercased = char.lowercased().first!
            if result.contains(lowercased) == false { disqualified.insert(lowercased) }
        } else {
            guard disqualified.contains(char) == false else { return }
            if let last = letters.lastIndex(of: char.uppercased().first!), last > index {
                if let lastLower = letters.lastIndex(of: char), lastLower > last { return }
                result.insert(char)
            }
        }
    }
    return result.count
}
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login