|
19 | 19 | */
|
20 | 20 | public class _432 {
|
21 | 21 |
|
22 |
| - |
23 |
| - /** |
24 |
| - * credit: https://discuss.leetcode.com/topic/65634/java-ac-all-strict-o-1-not-average-o-1-easy-to-read/2 |
25 |
| - */ |
26 |
| - class AllOne { |
27 |
| - // maintain a doubly linked list of Buckets |
28 |
| - private Bucket head; |
29 |
| - private Bucket tail; |
30 |
| - // for accessing a specific Bucket among the Bucket list in O(1) time |
31 |
| - private Map<Integer, Bucket> countBucketMap; |
32 |
| - // keep track of count of keys |
33 |
| - private Map<String, Integer> keyCountMap; |
34 |
| - |
35 |
| - // each Bucket contains all the keys with the same count |
36 |
| - private class Bucket { |
37 |
| - int count; |
38 |
| - Set<String> keySet; |
39 |
| - Bucket next; |
40 |
| - Bucket pre; |
41 |
| - |
42 |
| - public Bucket(int cnt) { |
43 |
| - count = cnt; |
44 |
| - keySet = new HashSet<>(); |
45 |
| - } |
46 |
| - } |
| 22 | + public static class Solution1 { |
47 | 23 |
|
48 | 24 | /**
|
49 |
| - * Initialize your data structure here. |
| 25 | + * credit: https://discuss.leetcode.com/topic/65634/java-ac-all-strict-o-1-not-average-o-1-easy-to-read/2 |
50 | 26 | */
|
51 |
| - public AllOne() { |
52 |
| - head = new Bucket(Integer.MIN_VALUE); |
53 |
| - tail = new Bucket(Integer.MAX_VALUE); |
54 |
| - head.next = tail; |
55 |
| - tail.pre = head; |
56 |
| - countBucketMap = new HashMap<>(); |
57 |
| - keyCountMap = new HashMap<>(); |
58 |
| - } |
59 |
| - |
60 |
| - /** |
61 |
| - * Inserts a new key <Key> with value 1. Or increments an existing key by 1. |
62 |
| - */ |
63 |
| - public void inc(String key) { |
64 |
| - if (keyCountMap.containsKey(key)) { |
65 |
| - changeKey(key, 1); |
66 |
| - } else { |
67 |
| - keyCountMap.put(key, 1); |
68 |
| - if (head.next.count != 1) { |
69 |
| - addBucketAfter(new Bucket(1), head); |
| 27 | + class AllOne { |
| 28 | + // maintain a doubly linked list of Buckets |
| 29 | + private Bucket head; |
| 30 | + private Bucket tail; |
| 31 | + // for accessing a specific Bucket among the Bucket list in O(1) time |
| 32 | + private Map<Integer, Bucket> countBucketMap; |
| 33 | + // keep track of count of keys |
| 34 | + private Map<String, Integer> keyCountMap; |
| 35 | + |
| 36 | + // each Bucket contains all the keys with the same count |
| 37 | + private class Bucket { |
| 38 | + int count; |
| 39 | + Set<String> keySet; |
| 40 | + Bucket next; |
| 41 | + Bucket pre; |
| 42 | + |
| 43 | + public Bucket(int cnt) { |
| 44 | + count = cnt; |
| 45 | + keySet = new HashSet<>(); |
70 | 46 | }
|
71 |
| - head.next.keySet.add(key); |
72 |
| - countBucketMap.put(1, head.next); |
73 | 47 | }
|
74 |
| - } |
75 | 48 |
|
76 |
| - /** |
77 |
| - * Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. |
78 |
| - */ |
79 |
| - public void dec(String key) { |
80 |
| - if (keyCountMap.containsKey(key)) { |
81 |
| - int count = keyCountMap.get(key); |
82 |
| - if (count == 1) { |
83 |
| - keyCountMap.remove(key); |
84 |
| - removeKeyFromBucket(countBucketMap.get(count), key); |
| 49 | + /** |
| 50 | + * Initialize your data structure here. |
| 51 | + */ |
| 52 | + public AllOne() { |
| 53 | + head = new Bucket(Integer.MIN_VALUE); |
| 54 | + tail = new Bucket(Integer.MAX_VALUE); |
| 55 | + head.next = tail; |
| 56 | + tail.pre = head; |
| 57 | + countBucketMap = new HashMap<>(); |
| 58 | + keyCountMap = new HashMap<>(); |
| 59 | + } |
| 60 | + |
| 61 | + /** |
| 62 | + * Inserts a new key <Key> with value 1. Or increments an existing key by 1. |
| 63 | + */ |
| 64 | + public void inc(String key) { |
| 65 | + if (keyCountMap.containsKey(key)) { |
| 66 | + changeKey(key, 1); |
85 | 67 | } else {
|
86 |
| - changeKey(key, -1); |
| 68 | + keyCountMap.put(key, 1); |
| 69 | + if (head.next.count != 1) { |
| 70 | + addBucketAfter(new Bucket(1), head); |
| 71 | + } |
| 72 | + head.next.keySet.add(key); |
| 73 | + countBucketMap.put(1, head.next); |
87 | 74 | }
|
88 | 75 | }
|
89 |
| - } |
90 | 76 |
|
91 |
| - /** |
92 |
| - * Returns one of the keys with maximal value. |
93 |
| - */ |
94 |
| - public String getMaxKey() { |
95 |
| - return tail.pre == head ? "" : (String) tail.pre.keySet.iterator().next(); |
96 |
| - } |
| 77 | + /** |
| 78 | + * Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. |
| 79 | + */ |
| 80 | + public void dec(String key) { |
| 81 | + if (keyCountMap.containsKey(key)) { |
| 82 | + int count = keyCountMap.get(key); |
| 83 | + if (count == 1) { |
| 84 | + keyCountMap.remove(key); |
| 85 | + removeKeyFromBucket(countBucketMap.get(count), key); |
| 86 | + } else { |
| 87 | + changeKey(key, -1); |
| 88 | + } |
| 89 | + } |
| 90 | + } |
97 | 91 |
|
98 |
| - /** |
99 |
| - * Returns one of the keys with Minimal value. |
100 |
| - */ |
101 |
| - public String getMinKey() { |
102 |
| - return head.next == tail ? "" : (String) head.next.keySet.iterator().next(); |
103 |
| - } |
| 92 | + /** |
| 93 | + * Returns one of the keys with maximal value. |
| 94 | + */ |
| 95 | + public String getMaxKey() { |
| 96 | + return tail.pre == head ? "" : (String) tail.pre.keySet.iterator().next(); |
| 97 | + } |
104 | 98 |
|
105 |
| - // helper function to make change on given key according to offset |
106 |
| - private void changeKey(String key, int offset) { |
107 |
| - int count = keyCountMap.get(key); |
108 |
| - keyCountMap.put(key, count + offset); |
109 |
| - Bucket curBucket = countBucketMap.get(count); |
110 |
| - Bucket newBucket; |
111 |
| - if (countBucketMap.containsKey(count + offset)) { |
112 |
| - // target Bucket already exists |
113 |
| - newBucket = countBucketMap.get(count + offset); |
114 |
| - } else { |
115 |
| - // add new Bucket |
116 |
| - newBucket = new Bucket(count + offset); |
117 |
| - countBucketMap.put(count + offset, newBucket); |
118 |
| - addBucketAfter(newBucket, offset == 1 ? curBucket : curBucket.pre); |
| 99 | + /** |
| 100 | + * Returns one of the keys with Minimal value. |
| 101 | + */ |
| 102 | + public String getMinKey() { |
| 103 | + return head.next == tail ? "" : (String) head.next.keySet.iterator().next(); |
119 | 104 | }
|
120 |
| - newBucket.keySet.add(key); |
121 |
| - removeKeyFromBucket(curBucket, key); |
122 |
| - } |
123 | 105 |
|
124 |
| - private void removeKeyFromBucket(Bucket bucket, String key) { |
125 |
| - bucket.keySet.remove(key); |
126 |
| - if (bucket.keySet.size() == 0) { |
127 |
| - removeBucketFromList(bucket); |
128 |
| - countBucketMap.remove(bucket.count); |
| 106 | + // helper function to make change on given key according to offset |
| 107 | + private void changeKey(String key, int offset) { |
| 108 | + int count = keyCountMap.get(key); |
| 109 | + keyCountMap.put(key, count + offset); |
| 110 | + Bucket curBucket = countBucketMap.get(count); |
| 111 | + Bucket newBucket; |
| 112 | + if (countBucketMap.containsKey(count + offset)) { |
| 113 | + // target Bucket already exists |
| 114 | + newBucket = countBucketMap.get(count + offset); |
| 115 | + } else { |
| 116 | + // add new Bucket |
| 117 | + newBucket = new Bucket(count + offset); |
| 118 | + countBucketMap.put(count + offset, newBucket); |
| 119 | + addBucketAfter(newBucket, offset == 1 ? curBucket : curBucket.pre); |
| 120 | + } |
| 121 | + newBucket.keySet.add(key); |
| 122 | + removeKeyFromBucket(curBucket, key); |
129 | 123 | }
|
130 |
| - } |
131 | 124 |
|
132 |
| - private void removeBucketFromList(Bucket bucket) { |
133 |
| - bucket.pre.next = bucket.next; |
134 |
| - bucket.next.pre = bucket.pre; |
135 |
| - bucket.next = null; |
136 |
| - bucket.pre = null; |
137 |
| - } |
| 125 | + private void removeKeyFromBucket(Bucket bucket, String key) { |
| 126 | + bucket.keySet.remove(key); |
| 127 | + if (bucket.keySet.size() == 0) { |
| 128 | + removeBucketFromList(bucket); |
| 129 | + countBucketMap.remove(bucket.count); |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + private void removeBucketFromList(Bucket bucket) { |
| 134 | + bucket.pre.next = bucket.next; |
| 135 | + bucket.next.pre = bucket.pre; |
| 136 | + bucket.next = null; |
| 137 | + bucket.pre = null; |
| 138 | + } |
138 | 139 |
|
139 |
| - // add newBucket after preBucket |
140 |
| - private void addBucketAfter(Bucket newBucket, Bucket preBucket) { |
141 |
| - newBucket.pre = preBucket; |
142 |
| - newBucket.next = preBucket.next; |
143 |
| - preBucket.next.pre = newBucket; |
144 |
| - preBucket.next = newBucket; |
| 140 | + // add newBucket after preBucket |
| 141 | + private void addBucketAfter(Bucket newBucket, Bucket preBucket) { |
| 142 | + newBucket.pre = preBucket; |
| 143 | + newBucket.next = preBucket.next; |
| 144 | + preBucket.next.pre = newBucket; |
| 145 | + preBucket.next = newBucket; |
| 146 | + } |
145 | 147 | }
|
146 | 148 | }
|
147 | 149 | }
|
|
0 commit comments