|
1 |
| -/* |
2 |
| - An Ordered Set is a collection where all items in the set follow an ordering, |
3 |
| - usually ordered from 'least' to 'most'. The way you value and compare items |
4 |
| - can be user-defined. |
5 |
| -*/ |
6 |
| -public struct OrderedSet<T: Comparable> { |
7 |
| - private var internalSet = [T]() |
8 |
| - |
9 |
| - public init() { } |
10 |
| - |
11 |
| - // Returns the number of elements in the OrderedSet. |
12 |
| - public var count: Int { |
13 |
| - return internalSet.count |
14 |
| - } |
15 |
| - |
16 |
| - // Inserts an item. Performance: O(n) |
17 |
| - public mutating func insert(_ item: T) { |
18 |
| - if exists(item) { |
19 |
| - return // don't add an item if it already exists |
20 |
| - } |
21 |
| - |
22 |
| - // Insert new the item just before the one that is larger. |
23 |
| - for i in 0..<count { |
24 |
| - if internalSet[i] > item { |
25 |
| - internalSet.insert(item, at: i) |
26 |
| - return |
27 |
| - } |
| 1 | +public class OrderedSet<T: Hashable> { |
| 2 | + private var objects: [T] = [] |
| 3 | + private var indexOfKey: [T: Int] = [:] |
| 4 | + |
| 5 | + public init() {} |
| 6 | + |
| 7 | + // O(1) |
| 8 | + public func add(_ object: T) { |
| 9 | + guard indexOfKey[object] == nil else { |
| 10 | + return |
28 | 11 | }
|
29 |
| - |
30 |
| - // Append to the back if the new item is greater than any other in the set. |
31 |
| - internalSet.append(item) |
| 12 | + |
| 13 | + objects.append(object) |
| 14 | + indexOfKey[object] = objects.count - 1 |
32 | 15 | }
|
33 |
| - |
34 |
| - // Removes an item if it exists. Performance: O(n) |
35 |
| - public mutating func remove(_ item: T) { |
36 |
| - if let index = index(of: item) { |
37 |
| - internalSet.remove(at: index) |
| 16 | + |
| 17 | + // O(n) |
| 18 | + public func insert(_ object: T, at index: Int) { |
| 19 | + assert(index < objects.count, "Index should be smaller than object count") |
| 20 | + assert(index >= 0, "Index should be bigger than 0") |
| 21 | + |
| 22 | + guard indexOfKey[object] == nil else { |
| 23 | + return |
38 | 24 | }
|
39 |
| - } |
40 |
| - |
41 |
| - // Returns true if and only if the item exists somewhere in the set. |
42 |
| - public func exists(_ item: T) -> Bool { |
43 |
| - return index(of: item) != nil |
44 |
| - } |
45 |
| - |
46 |
| - // Returns the index of an item if it exists, or -1 otherwise. |
47 |
| - public func index(of item: T) -> Int? { |
48 |
| - var leftBound = 0 |
49 |
| - var rightBound = count - 1 |
50 |
| - |
51 |
| - while leftBound <= rightBound { |
52 |
| - let mid = leftBound + ((rightBound - leftBound) / 2) |
53 |
| - |
54 |
| - if internalSet[mid] > item { |
55 |
| - rightBound = mid - 1 |
56 |
| - } else if internalSet[mid] < item { |
57 |
| - leftBound = mid + 1 |
58 |
| - } else if internalSet[mid] == item { |
59 |
| - return mid |
60 |
| - } else { |
61 |
| - // When we get here, we've landed on an item whose value is equal to the |
62 |
| - // value of the item we're looking for, but the items themselves are not |
63 |
| - // equal. We need to check the items with the same value to the right |
64 |
| - // and to the left in order to find an exact match. |
65 |
| - |
66 |
| - // Check to the right. |
67 |
| - for j in stride(from: mid, to: count - 1, by: 1) { |
68 |
| - if internalSet[j + 1] == item { |
69 |
| - return j + 1 |
70 |
| - } else if internalSet[j] < internalSet[j + 1] { |
71 |
| - break |
72 |
| - } |
73 |
| - } |
74 |
| - |
75 |
| - // Check to the left. |
76 |
| - for j in stride(from: mid, to: 0, by: -1) { |
77 |
| - if internalSet[j - 1] == item { |
78 |
| - return j - 1 |
79 |
| - } else if internalSet[j] > internalSet[j - 1] { |
80 |
| - break |
81 |
| - } |
82 |
| - } |
83 |
| - return nil |
84 |
| - } |
| 25 | + |
| 26 | + objects.insert(object, at: index) |
| 27 | + indexOfKey[object] = index |
| 28 | + for i in index+1..<objects.count { |
| 29 | + indexOfKey[objects[i]] = i |
85 | 30 | }
|
86 |
| - return nil |
87 | 31 | }
|
88 |
| - |
89 |
| - // Returns the item at the given index. |
90 |
| - // Assertion fails if the index is out of the range of [0, count). |
91 |
| - public subscript(index: Int) -> T { |
92 |
| - assert(index >= 0 && index < count) |
93 |
| - return internalSet[index] |
| 32 | + |
| 33 | + // O(1) |
| 34 | + public func object(at index: Int) -> T { |
| 35 | + assert(index < objects.count, "Index should be smaller than object count") |
| 36 | + assert(index >= 0, "Index should be bigger than 0") |
| 37 | + |
| 38 | + return objects[index] |
94 | 39 | }
|
95 |
| - |
96 |
| - // Returns the 'maximum' or 'largest' value in the set. |
97 |
| - public func max() -> T? { |
98 |
| - return count == 0 ? nil : internalSet[count - 1] |
| 40 | + |
| 41 | + // O(1) |
| 42 | + public func set(_ object: T, at index: Int) { |
| 43 | + assert(index < objects.count, "Index should be smaller than object count") |
| 44 | + assert(index >= 0, "Index should be bigger than 0") |
| 45 | + |
| 46 | + guard indexOfKey[object] == nil else { |
| 47 | + return |
| 48 | + } |
| 49 | + |
| 50 | + indexOfKey.removeValue(forKey: objects[index]) |
| 51 | + indexOfKey[object] = index |
| 52 | + objects[index] = object |
99 | 53 | }
|
100 |
| - |
101 |
| - // Returns the 'minimum' or 'smallest' value in the set. |
102 |
| - public func min() -> T? { |
103 |
| - return count == 0 ? nil : internalSet[0] |
| 54 | + |
| 55 | + // O(1) |
| 56 | + public func indexOf(_ object: T) -> Int { |
| 57 | + return indexOfKey[object] ?? -1 |
104 | 58 | }
|
105 |
| - |
106 |
| - // Returns the k-th largest element in the set, if k is in the range |
107 |
| - // [1, count]. Returns nil otherwise. |
108 |
| - public func kLargest(_ k: Int) -> T? { |
109 |
| - return k > count || k <= 0 ? nil : internalSet[count - k] |
| 59 | + |
| 60 | + // O(n) |
| 61 | + public func remove(_ object: T) { |
| 62 | + guard let index = indexOfKey[object] else { |
| 63 | + return |
| 64 | + } |
| 65 | + |
| 66 | + indexOfKey.removeValue(forKey: object) |
| 67 | + objects.remove(at: index) |
| 68 | + for i in index..<objects.count { |
| 69 | + indexOfKey[objects[i]] = i |
| 70 | + } |
110 | 71 | }
|
111 |
| - |
112 |
| - // Returns the k-th smallest element in the set, if k is in the range |
113 |
| - // [1, count]. Returns nil otherwise. |
114 |
| - public func kSmallest(_ k: Int) -> T? { |
115 |
| - return k > count || k <= 0 ? nil : internalSet[k - 1] |
| 72 | + |
| 73 | + public func all() -> [T] { |
| 74 | + return objects |
116 | 75 | }
|
117 | 76 | }
|
0 commit comments