0

I was presented this problem where I need to find matching numbers in a given array (socks) and print out how many socks found inside that array. Here is my code:

let numberOfSocks = 9
let socksArray = [10, 20, 20, 10, 10, 30, 50, 10]

func findSocks(numberOfSocks: Int, array: [Int]) {

    var arr = array
    var uniqueSocks = Array(Set(array))
    var matchedPairs = 0
    var sockCounter = 0

    for i in 0..<uniqueSocks.count { // After the search, remove the element at index
        sockCounter = 0
        for j in 0..<arr.count {
            if uniqueSocks[i] == arr[j] {
                sockCounter += 1 
                if sockCounter % 2 == 0 {
                    matchedPairs += 1
                    sockCounter = 0
                }
            }    
        }
    }
    print(matchedPairs)
}    
findSocks(numberOfSocks: numberOfSocks, array: socksArray)

Firstly, I have removed all the duplicates in the array so it gives me a list unique socks that I need to search for. However, I wanted to optimize this algorithm by remove the sock that I have already searched for, I have tried arr.remove(at:) but It gave me an out of bound, I have a feeling that arr.count is not updated correctly. Any help is welcome, thanks!

Brendon Cheung
  • 995
  • 9
  • 29
  • It may help you: https://stackoverflow.com/questions/27624331/unique-values-of-array-in-swift – Bubu Jul 26 '17 at 15:11
  • Removing element from collection while looping thru it is not ideal. You can try different approach with Dictionary data structure with better time complexity. – Breek Jul 26 '17 at 15:14

1 Answers1

2

I think that you're overthinking the problem, focusing on small details rather than the big picture. What you want to end up with is essentially a dictionary where the keys are the unique values in the array, and the values are the number of times those values appear in the array. So start with your dictionary:

var counts = [Int : Int]()

There's no need for your arr and numberOfSocks variables. Instead of the latter, just use socksArray.count, which clearly will always be in sync with the true size of the array.

Now loop through your socks. For each sock value, increment its count in the counts dictionary or, if it's not already in the dictionary, add it and give it a count of 1.

for sock in socks {
    if !counts.contains(sock) {
        counts[sock] = 1
    } else {
        counts[sock] = counts[sock] + 1
    }
}

There are more concise ways to do this, but I think that this one is the easiest to read.

NRitH
  • 13,441
  • 4
  • 41
  • 44