Skip to content

Commit 944e89e

Browse files
authored
Merge pull request #302 from sir-gon/feature/frequency_queries
Feature/frequency queries
2 parents f00375d + 315cbcd commit 944e89e

File tree

7 files changed

+5493
-0
lines changed

7 files changed

+5493
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package ae.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
/**
9+
* FrequencyQueries.
10+
*
11+
* @link Problem definition
12+
* [[docs/hackerrank/interview_preparation_kit/dictionaries_and_hashmaps/frequency-queries.md]]
13+
*/
14+
public class FrequencyQueries {
15+
private FrequencyQueries() {
16+
}
17+
18+
private static final long __INITIAL__ = 1L;
19+
20+
private static final int __INSERT__ = 1;
21+
private static final int __DELETE__ = 2;
22+
private static final int __SELECT__ = 3;
23+
24+
private static final int __NOT_FOUND__ = 0;
25+
private static final int __FOUND__ = 1;
26+
27+
Map<Long, Long> valueFreqs = new HashMap<>();
28+
Map<Long, List<Long>> freqMap = new HashMap<>();
29+
List<Integer> result = new ArrayList<>();
30+
31+
void insert(Long value) {
32+
Long currentFreqCount = this.valueFreqs.getOrDefault(value, null);
33+
Long newFreqCount;
34+
List<Long> newFreq;
35+
36+
newFreqCount = (currentFreqCount == null ? __INITIAL__ : currentFreqCount + 1L);
37+
valueFreqs.put(value, newFreqCount);
38+
39+
newFreq = freqMap.getOrDefault(newFreqCount, null);
40+
41+
// delete current frequency
42+
if (currentFreqCount != null) {
43+
freqMap.get(currentFreqCount).remove(value);
44+
if (freqMap.get(currentFreqCount).isEmpty()) {
45+
freqMap.remove(currentFreqCount);
46+
}
47+
}
48+
49+
// add new frequency
50+
if (newFreq == null) {
51+
newFreq = new ArrayList<>();
52+
newFreq.add(value);
53+
freqMap.put(newFreqCount, newFreq);
54+
} else {
55+
freqMap.get(newFreqCount).add(value);
56+
}
57+
}
58+
59+
void delete(Long value) {
60+
Long currentFreqCount = this.valueFreqs.getOrDefault(value, null);
61+
Long newFreqCount;
62+
List<Long> newFreq;
63+
64+
newFreqCount = (currentFreqCount == null ? 0 : currentFreqCount - 1L);
65+
if (newFreqCount > 0L) {
66+
valueFreqs.put(value, newFreqCount);
67+
68+
newFreq = freqMap.getOrDefault(newFreqCount, null);
69+
// add new frequency
70+
if (newFreq == null) {
71+
newFreq = new ArrayList<>();
72+
newFreq.add(value);
73+
freqMap.put(newFreqCount, newFreq);
74+
} else {
75+
freqMap.get(newFreqCount).add(value);
76+
}
77+
} else {
78+
valueFreqs.remove(value);
79+
}
80+
81+
// delete current frequency
82+
if (currentFreqCount != null) {
83+
freqMap.get(currentFreqCount).remove(value);
84+
if (freqMap.get(currentFreqCount).isEmpty()) {
85+
freqMap.remove(currentFreqCount);
86+
}
87+
}
88+
}
89+
90+
/**
91+
* FrequencyQueries.
92+
*/
93+
static List<Integer> freqQuery(List<List<Integer>> queries) {
94+
95+
FrequencyQueries fq = new FrequencyQueries();
96+
fq.result = new ArrayList<>();
97+
98+
for (List<Integer> query : queries) {
99+
int operation = query.get(0);
100+
long value = query.get(1);
101+
102+
switch (operation) {
103+
case __INSERT__:
104+
fq.insert(value);
105+
106+
break;
107+
case __DELETE__:
108+
fq.delete(value);
109+
110+
break;
111+
case __SELECT__:
112+
fq.result.add(fq.freqMap.containsKey(value) ? __FOUND__ : __NOT_FOUND__);
113+
break;
114+
default:
115+
throw new IllegalArgumentException(
116+
"Operation %d not supported".formatted(operation));
117+
}
118+
}
119+
120+
return fq.result;
121+
}
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package ae.hackerrank.interview_preparation_kit.dictionaries_and_hashmaps;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import java.io.IOException;
8+
import java.util.List;
9+
import org.junit.jupiter.api.BeforeAll;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.TestInstance;
12+
import org.junit.jupiter.api.TestInstance.Lifecycle;
13+
import util.JsonLoader;
14+
15+
@TestInstance(Lifecycle.PER_CLASS)
16+
class FrequencyQueriesTest {
17+
18+
public static class FrequencyQueriesTestCase {
19+
public String title;
20+
public List<List<Integer>> input;
21+
public List<Integer> expected;
22+
}
23+
24+
List<FrequencyQueriesTestCase> testCases;
25+
List<FrequencyQueriesTestCase> testCase6;
26+
List<FrequencyQueriesTestCase> testCaseBorderCases;
27+
List<FrequencyQueriesTestCase> testCaseBorderCaseException;
28+
29+
@BeforeAll
30+
void setup() throws IOException {
31+
String path;
32+
path = String.join("/",
33+
"hackerrank",
34+
"interview_preparation_kit",
35+
"dictionaries_and_hashmaps",
36+
"frequency_queries.testcases.json");
37+
38+
this.testCases = JsonLoader.loadJson(path, FrequencyQueriesTestCase.class);
39+
40+
path = String.join("/",
41+
"hackerrank",
42+
"interview_preparation_kit",
43+
"dictionaries_and_hashmaps",
44+
"frequency_queries.testcase6.json");
45+
this.testCase6 = JsonLoader.loadJson(path, FrequencyQueriesTestCase.class);
46+
47+
path = String.join("/",
48+
"hackerrank",
49+
"interview_preparation_kit",
50+
"dictionaries_and_hashmaps",
51+
"frequency_queries.testcase_border_cases.json");
52+
this.testCaseBorderCases = JsonLoader.loadJson(path, FrequencyQueriesTestCase.class);
53+
54+
path = String.join("/",
55+
"hackerrank",
56+
"interview_preparation_kit",
57+
"dictionaries_and_hashmaps",
58+
"frequency_queries.testcase_border_case_exception.json");
59+
this.testCaseBorderCaseException = JsonLoader.loadJson(path, FrequencyQueriesTestCase.class);
60+
}
61+
62+
@Test
63+
void testFrequencyQueries() {
64+
List<Integer> solutionFound;
65+
66+
for (FrequencyQueriesTestCase test : testCases) {
67+
solutionFound = FrequencyQueries.freqQuery(test.input);
68+
69+
assertEquals(test.expected, solutionFound,
70+
"%s(%s) answer must be: %s".formatted(
71+
"FrequencyQueriesTest.freqQuery",
72+
test.input,
73+
test.expected));
74+
}
75+
}
76+
77+
@Test
78+
void testFrequencyQueriesBigCases() {
79+
List<Integer> solutionFound;
80+
81+
for (FrequencyQueriesTestCase test : testCase6) {
82+
83+
solutionFound = FrequencyQueries.freqQuery(test.input);
84+
85+
assertEquals(test.expected, solutionFound,
86+
"%s(%s) answer must be: %s".formatted(
87+
"FrequencyQueriesTest.freqQuery",
88+
test.input,
89+
test.expected));
90+
}
91+
}
92+
93+
@Test
94+
void testFrequencyQueriesBorderCases() {
95+
List<Integer> solutionFound;
96+
97+
for (FrequencyQueriesTestCase test : testCaseBorderCases) {
98+
99+
solutionFound = FrequencyQueries.freqQuery(test.input);
100+
101+
assertEquals(test.expected, solutionFound,
102+
"%s(%s) answer must be: %s".formatted(
103+
"FrequencyQueriesTest.freqQuery",
104+
test.input,
105+
test.expected));
106+
}
107+
}
108+
109+
@Test
110+
void testFrequencyQueriesBorderCaseException() {
111+
for (FrequencyQueriesTestCase test : testCaseBorderCaseException) {
112+
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
113+
FrequencyQueries.freqQuery(test.input);
114+
});
115+
116+
String expectedMessage = "Operation 4 not supported";
117+
String actualMessage = exception.getMessage();
118+
119+
assertTrue(actualMessage.contains(expectedMessage));
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)