简体   繁体   中英

Q re: cleaning up an an array without moving indexes

I'm attempting to complete HackerRank's Abbreviation challenge in Swift.

The physics for poets of what I'm trying to determine if a given abbreviation can be formed with a given string. You're given a string and an abbreviation they'd like formed with it. The curve ball is you can only delete characters or change their case...you can't swap indexes on them.

I'm able to complete most of the validating and cleanup of the string they give me, but I'm stuck on a part where I can only delete characters, but not swap indexes.

let abbrArray = abbreviation.characters.map({String($0)})
var matchingCharArray = capitalizedInputArray.filter({abbrArray.contains($0)})

I'm trying to run through each element of the abbreviation array remove characters at the front of the matchingCharArray that don't match the character in the abbrArray 's index.

Here's my code for that portion:

for index in 0..<abbrArray.count {
    let charToEvaluate = abbrArray[index]
    while matchingCharArray.first != charToEvaluate {
        matchingCharArray.removeFirst()
    }
}

if matchingCharArray.joined().range(of: abbreviation) == nil {
    return "NO"
}

Here's a link to the code on Swift Sandbox .

Any suggestions re: how I can clean up my matchingCharArray array without moving indexes is greately appreciated.

The trick with this challenge, is that you don't need to produce the output array , you simply need to answer "yes" or "no" as to whether you could produce the output array. And this answer can be determined by answering the question "Does the sequence of letters in the 'abbreviation' exist in the input string in order, given that there may be other characters between the target letters?" Of course, you also need to consider that some of the target letters may be in lower case.

Since the order of the strings is important, this pretty much rules out using sets. My approach would be:

  1. Convert the entire input string to uppercase
  2. Iterate through the input string looking for the first character in the abbreviation
  3. If you find it, return to step 2, looking for the next character in the abbreviation
  4. If you reach the end of the abbreviation string, return "YES"
  5. If you reach the end of the input string before you find the final character in the abbreviation, return "NO".

My answer in Swift is:

func canBeAbbreviated(input: String, abbreviation: String) -> String {

    var retValue = "NO"

    let inputCharacters = input.uppercased().characters
    let abbreviationCharacters = abbreviation.characters
    var inputIndex = inputCharacters.startIndex
    var abbreviationIndex = abbreviationCharacters.startIndex

    while abbreviationIndex < abbreviationCharacters.endIndex {
        while inputIndex < inputCharacters.endIndex {

            let iChar = inputCharacters[inputIndex]
            let aChar = abbreviationCharacters[abbreviationIndex]
            inputIndex = inputCharacters.index(after: inputIndex)

           if iChar == aChar {
                abbreviationIndex = abbreviationCharacters.index(after: abbreviationIndex)
                break
            }
        }
        if inputIndex == inputCharacters.endIndex {
            break;
        }
    }

    if abbreviationIndex == abbreviationCharacters.endIndex {
        retValue = "YES"
    }

    return retValue
}

Paulw11 answer is correct, thats what I did, but then if follow the explanation in the page, I got this to replace the stuck part for you, it should remove all unnecessary character from the matchingCharArray , also you can use abbrArray.filter({capitalizedInputArray.contains($0)}) and compare the count it with the abbrArray itself then enough to replace the whole middle part already:

var i = 0
var indexToRemove = [Int]()
for char in abbrArray {
    while i < matchingCharArray.count {
        if matchingCharArray[i] != char {
            indexToRemove.append(i)
            i+=1
        } else {
            i+=1
            break
        }
    }
}

if i < matchingCharArray.count - 1 {
    matchingCharArray.removeSubrange(i...matchingCharArray.count-1)
}

for j in indexToRemove.reversed() {
    matchingCharArray.remove(at: j)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM