PrevNext
Not Frequent
 0/7

Introduction to Sets & Maps

Authors: Darren Yao, Benjamin Qi, Allen Li

Sorting, and maintaining collections of distinct elements with ordered sets.

Resources
IUSACOmodule is based off this
CPHcovers similar material

Both Java and C++ contain two versions of sets and maps; one using sorting and the other using hashing. We'll only introduce the former version in this module.

Sets

Focus Problem – read through this problem before continuing!

A set is a collection of objects that contains no duplicates. In ordered sets, the entries are sorted in order of key. Insertions, deletions, and searches are all O(logN)O(\log N), where NN is the number of elements in the set.

C++

The operations on a C++ set include:

  • insert, which adds an element to the set if not already present.
  • erase, which deletes an element if it exists.
  • count, which returns 1 if the set contains the element and 0 if it doesn't.
set<int> s;
s.insert(1); // [1]
s.insert(4); // [1, 4]
s.insert(2); // [1, 2, 4]
s.insert(1); // [1, 2, 4]
// the add method did nothing because 1 was already in the set
cout << s.count(1) << endl; // 1
s.erase(1); // [2, 4]
cout << s.count(5) << endl; // 0
s.erase(0); // [2, 4]

Java

The operations on a TreeSet are add, which adds an element to the set if not already present, remove, which deletes an element if it exists, and contains, which checks whether the set contains that element.

Set<Integer> set = new TreeSet<Integer>();
set.add(1); // [1]
set.add(4); // [1, 4]
set.add(2); // [1, 2, 4]
set.add(1); // [1, 2, 4]
// the add method did nothing because 1 was already in the set
System.out.println(set.contains(1)); // true
set.remove(1); // [2, 4]
System.out.println(set.contains(5)); // false
set.remove(0); // [2, 4]

Python

Warning!

Ordered sets and maps are not built into Python. The Python OrderedDict stores keys in the same order as they were inserted in, not in sorted order.

The built in python unsorted set supports:

  • add(): Adds element to set
  • remove(): Removes element from set
  • x in set: Checks if element x is in the set
set = set()
set.add(1) # [1]
set.add(4) # [1, 4]
set.add(2) # [1, 4, 2]
set.add(1) # [1, 4, 2]
# the add method did nothing because 1 was already in the set
print(1 in set) # True
set.remove(1) # [4, 2]
print(5 in set) # False
set.remove(0); # [4, 2]

Solution - Distinct Numbers

This problem asks us to calculate the number of distinct values in a given list.

Method 1 - Set

This is probably the easier of the two methods, but requires knowledge of sets. Because sets only store one copy of each value, we can insert all the numbers into a set, and then print out the size of the set.

C++

#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
set<int> distinctNumbers;

Java

// Source: Daniel
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.StringTokenizer;
public class DistinctNumbers {

Python

n = int(input())
nums = [int(x) for x in input().split()]
distinctNumbers = set(nums)
print(len(distinctNumbers))

Method 2 - Sorting the Array

This problem is also solvable without sets. Sort a vector containing all the numbers. The answer is the number of times two adjacent numbers are not equal; more formally, the number of times aiai+1a_i \neq a_{i + 1}, plus one.

C++

#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int A[n];

Java

import java.io.*;
import java.util.*;
public class DistinctNumbers {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] arr = new int[n];

Python

n = int(input())
arr = [int(x) for x in input().split()]
arr = sorted(arr)
ans = 1
for i in range(n - 1):
if arr[i] != arr[i + 1]:
ans += 1
print(ans)

Maps

Focus Problem – read through this problem before continuing!

A map is a set of ordered pairs, each containing a key and a value. In a map, all keys are required to be unique, but values can be repeated. Maps have three primary methods:

  • one to add a specified key-value pairing
  • one to retrieve the value for a given key
  • one to remove a key-value pairing from the map

Insertions, deletions, and searches are all O(logN)O(\log N), where NN is the number of elements in the map.

C++

In a C++ map m:

  • the m[key] = value operator assigns a value to a key and places the key and value pair into the map. The operator m[key] returns the value associated with the key. If the key is not present in the map, then m[key] is set to 0.
  • The count(key) method returns the number of times the key is in the map (which is either one or zero), and therefore checks whether a key exists in the map.
  • Lastly, erase(key) removes the map entry associated with the specified key.
map<int, int> m;
m[1] = 5; // [(1, 5)]
m[3] = 14; // [(1, 5); (3, 14)]
m[2] = 7; // [(1, 5); (2, 7); (3, 14)]
m[0] = -1; // [(0, -1); (1, 5); (2, 7); (3, 14)]
m.erase(2); // [(0, -1); (1, 5); (3, 14)]
cout << m[1] << '\n'; // 5
cout << m.count(7) << '\n' ; // 0
cout << m.count(1) << '\n' ; // 1

Java

In a TreeMap, the put(key, value) method assigns a value to a key and places the key and value pair into the map. The get(key) method returns the value associated with the key. The containsKey(key) method checks whether a key exists in the map. Lastly, remove(key) removes the map entry associated with the specified key. All of these operations are O(1)O(1), but again, due to the hashing, this has a high constant factor.

Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
map.put(1, 5); // [(1, 5)]
map.put(3, 14); // [(1, 5); (3, 14)]
map.put(2, 7); // [(1, 5); (2, 7); (3, 14)]
map.remove(2); // [(1, 5); (3, 14)]
System.out.println(map.get(1)); // 5
System.out.println(map.containsKey(7)); // false
System.out.println(map.containsKey(1)); // true

Python

Colloquially, maps are referred to as dicts in python. They act as hash maps, so they actually have O(1)O(1) insertion, deletion, and searches.

dict = {}
dict[1] = 5 # [(1, 5)]
dict[3] = 14 # [(1, 5); (3, 14)]
dict[2] = 7 # [(1, 5); (2, 7); (3, 14)]
del dict[2] # [(1, 5); (3, 14)]
print(dict[1]) # 5
print(7 in dict.keys()) # False
print(1 in dict.keys()) # True

Iterating Over Maps

C++

To iterate over maps, you can use a for loop.

for (pair<int,int> x : m) {
cout << x.first << " " << x.second << '\n';
}
for (auto x : m) {
cout << x.first << " " << x.second << '\n';
}
/* both output the following:
0 -1
1 5

The map stores pairs in the form {key, value}. The auto keyword suffices to iterate over any type of pair. You can use these pairs normally, as introduced in this module.

Additionally, you can pass by reference when iterating over a map, like this:

for (auto& x : m) {
x.second = 3;
}
for (pair<int,int> x : m) {
cout << x.first << " " << x.second << '\n';
}
/*
0 3
1 3

This allows you to modify the values of the pairs stored in the map.

Java

To iterate over maps, you can use a for loop over the keys.

for (int k : m.keySet()){
System.out.println(k + " " + m.get(k));
}

Python

To iterate over dicts, you can use a for loop over the keys of the dict.

for key in dict.keys():
print(f'{key} {dict[key]}')

Problems

Some of these problems can be solved by sorting alone.

StatusSourceProblem NameDifficultyTagsSolution
BronzeEasyExternal Sol
CSESEasy
BronzeEasyExternal Sol
BronzeNormalExternal Sol
SilverNormalExternal Sol

Give Us Feedback on Introduction to Sets & Maps!

Module Progress:

PrevNext