Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python to Intro_Sorted_Sets Module #4862

Merged
merged 25 commits into from
Oct 29, 2024
Merged
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
85f0dec
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 25, 2024
ed8ee72
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 25, 2024
63623f3
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
18e4f28
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
130db1d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
a6f6fb3
Merge branch 'master' into py
CryoJS Oct 27, 2024
8cff55d
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
bc4edd7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
6f15cf1
Update Intro_Sorted_Sets.mdx
SansPapyrus683 Oct 27, 2024
a24ed0b
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
4a17b5b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
89925ad
Merge branch 'master' into py
CryoJS Oct 27, 2024
fe11a65
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
c0be548
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
52c16ef
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
d03d27d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2024
33a8818
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 27, 2024
36db49f
Merge branch 'master' into py
CryoJS Oct 28, 2024
c68a350
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 28, 2024
8579ef3
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 28, 2024
7857cb3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 28, 2024
12b1166
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 28, 2024
d31adae
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 28, 2024
9a95d1a
Merge branch 'master' into py
CryoJS Oct 29, 2024
4cc8617
Update content/3_Silver/Intro_Sorted_Sets.mdx
CryoJS Oct 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 174 additions & 9 deletions content/3_Silver/Intro_Sorted_Sets.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
id: intro-sorted-sets
title: 'More Operations on Sorted Sets'
author: Darren Yao, Benjamin Qi, Andrew Wang
contributors: Aadit Ambadkar, Jeffrey Hu
contributors: Aadit Ambadkar, Jeffrey Hu, Jason Sun
prerequisites:
- intro-sets
description:
Expand Down Expand Up @@ -48,10 +48,10 @@ redirects:
In sets and maps where keys (or elements) are stored in sorted order, accessing
or removing the next key higher or lower than some input key `k` is supported.

Keep in mind that insertion and deletion will take $\mathcal{O}(\log N)$ time for
sorted sets, which is more than the average $\mathcal{O}(1)$ insertion and
deletion for unordered sets, but less than the worst case $\mathcal{O}(N)$ insertion
and deletion for unordered sets.
Keep in mind that insertion and deletion will take $\mathcal{O}(\log N)$ time
for sorted sets, which is more than the average $\mathcal{O}(1)$ insertion and
deletion for unordered sets, but less than the worst case $\mathcal{O}(N)$
insertion and deletion for unordered sets.

## Using Iterators

Expand Down Expand Up @@ -126,6 +126,31 @@ which can only be used once before calling the `next()` method.

</JavaSection>

<PySection>

In Python, we can use `iter()` to obtain the iterator object of any iterable.
This returns the first element, and using `next()` on the iterator gives you the
next one. Below, a dictionary is used instead of a set because dictionaries keep
order.

```py
nums = {1: None, 7: None, 0: None, 2: None, 4: None}
CryoJS marked this conversation as resolved.
Show resolved Hide resolved
iterator = iter(nums)

print(iterator) # <set_iterator object at 0x14765f3eb6c0>
CryoJS marked this conversation as resolved.
Show resolved Hide resolved
print(next(iterator)) # 1
print(next(iterator)) # 7
print(next(iterator)) # 0
print(next(iterator)) # 2
print(next(iterator)) # 4
```

<Warning>
As of Python 3.6, dictionaries are ordered by **insertion order**. You can also use an `OrderedDict` from `collections`, which is built with the goal of being ordered and thus has more features and slightly different speeds compared to a regular Python dictionary.
</Warning>
CryoJS marked this conversation as resolved.
Show resolved Hide resolved

</PySection>

</LanguageSection>

## Sorted Sets
Expand Down Expand Up @@ -197,6 +222,74 @@ System.out.println(set.higher(23)); // ERROR, no such element exists

</JavaSection>

<PySection>

Python does not have a sorted set, so see the C++ or Java if you want an
implementation from the standard library.

Creating a sorted set from scratch is time consuming, and not reccomended to do
so in contests, but if you are curious regarding the implementation, you can
find an AVL tree implementation of a sorted set below.

<Resources>
<Resource source="DSA Python" url="https://nibmehub.com/opac-service/pdf/read/Data%20Structures%20and%20Algorithms%20in%20Python.pdf#page=503" title="AVL Trees">
Read about the definition and implementation of AVL Trees in Python
</Resource>
</Resources>

<Warning>

You are not expected to know how to create an AVL tree in the silver division.

</Warning>

Since some online judges include additional libraries, there is also an
implementation of sorted sets included from the `sortedcontainers` library. All
operations shown below are $\mathcal{O}(\log N)$ time, except for its
$\mathcal{O}(N \log N)$ initialization.

```py
from sortedcontainers import SortedSet

sorted_set = SortedSet([5, 1, 3, 2])
print(sorted_set) # SortedSet([1, 2, 3, 4, 7])

# Add elements
sorted_set.add(4)
sorted_set.add(6)
print(sorted_set) # SortedSet([1, 2, 3, 4, 5, 6])

# Remove elements
sorted_set.discard(3)
sorted_set.discard(5)
print(sorted_set) # SortedSet([1, 2, 4, 6])

# Check if an element is in the sorted set
print(2 in sorted_set) # True
print(100 in sorted_set) # False

# Access elements by it's index
print(sorted_set[0]) # 1 (smallest element, first index)
print(sorted_set[-1]) # 6 (largest element, last index)
print(sorted_set[2]) # 4

# Get the index of an element
print(sorted_set.index(4)) # 2

# Find the index to insert the given value
print(sorted_set.bisect_left(2)) # 1
print(sorted_set.bisect_right(2)) # 2
```

<Warning>

The `sortedcontainers` library is not part of Python's standard library. This
means that most online judges do **not** provide it (including USACO).

</Warning>

</PySection>

</LanguageSection>

One limitation of sorted sets is that we can't efficiently access the $k^{th}$
Expand Down Expand Up @@ -256,6 +349,73 @@ System.out.println(map.lowerKey(3)); // ERROR

</JavaSection>

<PySection>

Python does not have built in sorted maps or sorted sets in it's standard
library. However, sorted maps in Python can be created by adding a dictionary to
a sorted set, where each element in the sorted set is a key in the dictionary
and values can be assigned with the dictionary.
CryoJS marked this conversation as resolved.
Show resolved Hide resolved

This is the most straightforward implementation, and the ground up
implementation of a sorted set can be found in the above section.

Since some online judges include additional libraries, an implementation of
`SortedDict` from the `sortedcontainers` library can be found below. All
operations shown below are $\mathcal{O}(\log N)$ time, except for its
$\mathcal{O}(N \log N)$ initialization and getting all items, keys, or values
which is $\mathcal{O}(N)$ time.

```py
from sortedcontainers import SortedDict

sorted_map = SortedDict({1: "one", 4: "four", 3: "three"})
print(sorted_map) # SortedDict({1: 'one', 3: 'three', 4: 'four'})

# Add elements
sorted_map[2] = "two"
sorted_map[5] = "five"
print(sorted_map) # SortedDict({1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'})

# Remove elements
del sorted_map[3]
print(sorted_map) # SortedDict({1: 'one', 2: 'two', 4: 'four', 5: 'five'})

# Check if a key is in the sorted dict
print(1 in sorted_map) # True
print(100 in sorted_map) # False

# Get the key's value
print(sorted_map[2]) # two
print(sorted_map[4]) # four

# Get all items (key value pairs), keys, or values
print(
sorted_map.items()
) # SortedItemsView(SortedDict({1: 'one', 2: 'two', 4: 'four', 5: 'five'}))
print(
sorted_map.keys()
) # SortedKeysView(SortedDict({1: 'one', 2: 'two', 4: 'four', 5: 'five'}))
CryoJS marked this conversation as resolved.
Show resolved Hide resolved
print(
sorted_map.values()
) # SortedValuesView(SortedDict({1: 'one', 2: 'two', 4: 'four', 5: 'five'}))

# Find the index of an existing key
print(sorted_map.index(2)) # 1

# Find the index to insert a given key
print(sorted_map.bisect_left(3)) # 2
print(sorted_map.bisect_right(6)) # 4
```

<Warning>

The `sortedcontainers` library is not part of Python's standard library. This
means that most online judges do **not** provide it (including USACO).

</Warning>

</PySection>

</LanguageSection>

## Multisets
Expand All @@ -271,8 +431,8 @@ In addition to all of the regular set operations,
- the `count()` method returns the number of times an element is present in the
multiset. However, this method takes time **linear** in the number of matches
so you shouldn't use it in a contest.
- To remove a value __once__, use `ms.erase(ms.find(val))`.
- To remove __all__ occurrences of a value, use `ms.erase(val)`.
- To remove a value **once**, use `ms.erase(ms.find(val))`.
- To remove **all** occurrences of a value, use `ms.erase(val)`.

<Warning>
Using `ms.erase(val)` erases __all__ instances of `val` from the multiset. To remove one instance of `val`, use `ms.erase(ms.find(val))`!
Expand Down Expand Up @@ -392,11 +552,16 @@ pq.add(6); // [7, 6, 5]

In Python (unlike in C++), we delete and retrieve the **lowest** element.

Note that Python's priority queue is not encapsulated; `heapq` operates on a provided list directly by turning it into a heap, then doing operations on the heap.
Note that Python's priority queue is not encapsulated; `heapq` operates on a
provided list directly by turning it into a heap, then doing operations on the
heap.

<Warning>

Because of a heap's structure, printing out `pq` will **not** print out the elements in sorted order in Python; instead, it will print out the list. The comments below are a **representation** of what the heap contains, **not** what the contents of `pq` actually are.
Because of a heap's structure, printing out `pq` will **not** print out the
elements in sorted order in Python; instead, it will print out the list. The
comments below are a **representation** of what the heap contains, **not** what
the contents of `pq` actually are.

</Warning>

Expand Down
Loading