Unique Number of Occurrences

Hello Guys,

My solution to the question below works with positive numbers but fail when a negative is caught. For example [-3,0,1,-3,1,1,1,-3,10,0] returns true but mine return false. How do I resolve this ?

Given an array of integers arr , return true if the number of occurrences of each value in the array is unique , or false otherwise.

Example 1:

Input: arr = [1,2,2,1,1,3] Output: true Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number of occurrences.

Example 2:

Input: arr = [1,2] Output: false

Example 3:

Input: arr = [-3,0,1,-3,1,1,1,-3,10,0] Output: true

func uniqueOccurrences(_ arr: [Int]) -> Bool {
    var result = [Int:Int]()
    let numbers = Set(arr)
    
    for nums in arr{
        if let value = result[nums]{
            result[nums] = value+1
        }
        else{
            result[nums] = 1
        }
    }
    print(result)
    
    for k in result.values{
        if numbers.contains(k) && k >= 2  {
            return true
        }
    }
    return false
}


uniqueOccurrences([1,2,3,45,6,7,8,9,9,])

I believe you've misread the problem statement, so you'll want to reevaluate what your second loop is doing.

1 Like

Is this a continuation of your problem from last month?

[-3,0,1,-3,1,1,1,-3,10,0].hasUniqueBuckets // true
public extension Sequence where Element: Hashable {
  var containsOnlyUniqueElements: Bool {
    do {
      _ = try Set(unique: self)
      return true
    } catch {
      return false
    }
  }

  var hasUniqueBuckets: Bool {
    Dictionary(bucketing: self).values.containsOnlyUniqueElements
  }
}
public extension SetAlgebra {
  /// - Throws: if `elements` contains any duplicates.
  init<Elements: Sequence>(unique elements: Elements) throws
  where Elements.Element == Element {
    self = try elements.reduce(into: .init()) {
      guard $0.insert($1).inserted
      else { throw Error() }
    }
  }
}

private struct Error: Swift.Error { }
public extension Dictionary where Value == Int {
  /// Create "buckets" from a sequence of keys,
  /// such as might be used for a histogram.
  init<Keys: Sequence>(bucketing unbucketedKeys: Keys)
  where Keys.Element == Key {
    self.init(zip(unbucketedKeys, 1), uniquingKeysWith: +)
  }
}
/// `zip` a sequence with a single value, instead of another sequence.
@inlinable public func zip<Sequence: Swift.Sequence, Constant>(
  _ sequence: Sequence, _ constant: Constant
) -> LazyMapSequence<
  LazySequence<Sequence>.Elements,
  (LazySequence<Sequence>.Element, Constant)
> {
 sequence.lazy.map { ($0, constant) }
}

Hey Jessey,
Thanks for the solution; It's not. Its a different question from leet code

Thanks for the response. I sort of understand the question. My thought process for using the set was to check if values occurred more than twice in the hash map

I would not call it different. As shown above, to me, this is the same question, with the requirement of forming buckets first.

If you're asking about practice questions, it's useful to post the original question as part of it too. So we can know if there's any misinterpretation to begin with.

sorry about that

In any case, if the question is as you said, I do agree that the second loop is very suspicious.

func uniqueOccurrences(_ xs: [Int]) -> Bool {
    let occurrences = Set(xs).map { x in xs.filter { x == $0 }.count }
    return Set(occurrences).count == occurrences.count
}

Just like with your other post, you created a dictionary (result), but only read the values. That doesn't make any sense.

I think it makes sense in this case. You can use the dictionary to track how many times you've seen each element, but you only care that the values are unique at the end.

func uniqueOccurrences(_ array: [Int]) -> Bool {
    let counts = array.reduce(into: [Int: Int]()) { counts, element in
        counts[element, default: 0] += 1
    }

    return counts.values.count == Set(counts.values).count
}
1 Like

Nice solution bro !!!

That is exactly the same as my solution, with extra steps.

That reduce call is how we used to do it before Swift 4.0's Dictionary(_: uniquingKeysWith:).

And reduce is how we do it now with reduce(into:). No need for AnyIterator, no need for zip. More readable, possibly faster.

Use unbucketedKeys.lazy.map { ($0, 1) } then. (I just added a zip overload above for that.) If you'd still rather use reduce, you should petition for the removal of the Dictionary initializer.

Why? Just because it's not useful in this narrow case doesn't mean it's not useful. This is all getting rather off topic anyway

2 Likes