Create number container system algorithm
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 231b0e2f1d2f..6dac4a9a5783 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -419,8 +419,9 @@
   * [Frequent Pattern Graph Miner](graphs/frequent_pattern_graph_miner.py)
   * [G Topological Sort](graphs/g_topological_sort.py)
   * [Gale Shapley Bigraph](graphs/gale_shapley_bigraph.py)
+  * [Graph Adjacency List](graphs/graph_adjacency_list.py)
+  * [Graph Adjacency Matrix](graphs/graph_adjacency_matrix.py)
   * [Graph List](graphs/graph_list.py)
-  * [Graph Matrix](graphs/graph_matrix.py)
   * [Graphs Floyd Warshall](graphs/graphs_floyd_warshall.py)
   * [Greedy Best First](graphs/greedy_best_first.py)
   * [Greedy Min Vertex Cover](graphs/greedy_min_vertex_cover.py)
@@ -479,6 +480,7 @@
     * [Lib](linear_algebra/src/lib.py)
     * [Polynom For Points](linear_algebra/src/polynom_for_points.py)
     * [Power Iteration](linear_algebra/src/power_iteration.py)
+    * [Rank Of Matrix](linear_algebra/src/rank_of_matrix.py)
     * [Rayleigh Quotient](linear_algebra/src/rayleigh_quotient.py)
     * [Schur Complement](linear_algebra/src/schur_complement.py)
     * [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py)
@@ -651,6 +653,7 @@
   * [Sigmoid Linear Unit](maths/sigmoid_linear_unit.py)
   * [Signum](maths/signum.py)
   * [Simpson Rule](maths/simpson_rule.py)
+  * [Simultaneous Linear Equation Solver](maths/simultaneous_linear_equation_solver.py)
   * [Sin](maths/sin.py)
   * [Sock Merchant](maths/sock_merchant.py)
   * [Softmax](maths/softmax.py)
@@ -726,6 +729,7 @@
   * [Maximum Subarray](other/maximum_subarray.py)
   * [Maximum Subsequence](other/maximum_subsequence.py)
   * [Nested Brackets](other/nested_brackets.py)
+  * [Number Container System](other/number_container_system.py)
   * [Password](other/password.py)
   * [Quine](other/quine.py)
   * [Scoring Algorithm](other/scoring_algorithm.py)
diff --git a/other/number_container_system.py b/other/number_container_system.py
new file mode 100644
index 000000000000..f547bc8a229e
--- /dev/null
+++ b/other/number_container_system.py
@@ -0,0 +1,180 @@
+"""
+A number container system that uses binary search to delete and insert values into
+arrays with O(n logn) write times and O(1) read times.
+
+This container system holds integers at indexes.
+
+Further explained in this leetcode problem
+> https://leetcode.com/problems/minimum-cost-tree-from-leaf-values
+"""
+
+
+class NumberContainer:
+    def __init__(self) -> None:
+        # numbermap keys are the number and its values are lists of indexes sorted
+        # in ascending order
+        self.numbermap: dict[int, list[int]] = {}
+        # indexmap keys are an index and it's values are the number at that index
+        self.indexmap: dict[int, int] = {}
+
+    def binary_search_delete(self, array: list | str | range, item: int) -> list[int]:
+        """
+        Removes the item from the sorted array and returns
+        the new array.
+
+        >>> NumberContainer().binary_search_delete([1,2,3], 2)
+        [1, 3]
+        >>> NumberContainer().binary_search_delete([0, 0, 0], 0)
+        [0, 0]
+        >>> NumberContainer().binary_search_delete([-1, -1, -1], -1)
+        [-1, -1]
+        >>> NumberContainer().binary_search_delete([-1, 0], 0)
+        [-1]
+        >>> NumberContainer().binary_search_delete([-1, 0], -1)
+        [0]
+        >>> NumberContainer().binary_search_delete(range(7), 3)
+        [0, 1, 2, 4, 5, 6]
+        >>> NumberContainer().binary_search_delete([1.1, 2.2, 3.3], 2.2)
+        [1.1, 3.3]
+        >>> NumberContainer().binary_search_delete("abcde", "c")
+        ['a', 'b', 'd', 'e']
+        >>> NumberContainer().binary_search_delete([0, -1, 2, 4], 0)
+        Traceback (most recent call last):
+            ...
+        ValueError: Either the item is not in the array or the array was unsorted
+        >>> NumberContainer().binary_search_delete([2, 0, 4, -1, 11], -1)
+        Traceback (most recent call last):
+            ...
+        ValueError: Either the item is not in the array or the array was unsorted
+        >>> NumberContainer().binary_search_delete(125, 1)
+        Traceback (most recent call last):
+            ...
+        TypeError: binary_search_delete() only accepts either a list, range or str
+        """
+        if isinstance(array, (range, str)):
+            array = list(array)
+        elif not isinstance(array, list):
+            raise TypeError(
+                "binary_search_delete() only accepts either a list, range or str"
+            )
+
+        low = 0
+        high = len(array) - 1
+
+        while low <= high:
+            mid = (low + high) // 2
+            if array[mid] == item:
+                array.pop(mid)
+                return array
+            elif array[mid] < item:
+                low = mid + 1
+            else:
+                high = mid - 1
+        raise ValueError(
+            "Either the item is not in the array or the array was unsorted"
+        )
+
+    def binary_search_insert(self, array: list | str | range, index: int) -> list[int]:
+        """
+        Inserts the index into the sorted array
+        at the correct position.
+
+        >>> NumberContainer().binary_search_insert([1,2,3], 2)
+        [1, 2, 2, 3]
+        >>> NumberContainer().binary_search_insert([0,1,3], 2)
+        [0, 1, 2, 3]
+        >>> NumberContainer().binary_search_insert([-5, -3, 0, 0, 11, 103], 51)
+        [-5, -3, 0, 0, 11, 51, 103]
+        >>> NumberContainer().binary_search_insert([-5, -3, 0, 0, 11, 100, 103], 101)
+        [-5, -3, 0, 0, 11, 100, 101, 103]
+        >>> NumberContainer().binary_search_insert(range(10), 4)
+        [0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9]
+        >>> NumberContainer().binary_search_insert("abd", "c")
+        ['a', 'b', 'c', 'd']
+        >>> NumberContainer().binary_search_insert(131, 23)
+        Traceback (most recent call last):
+            ...
+        TypeError: binary_search_insert() only accepts either a list, range or str
+        """
+        if isinstance(array, (range, str)):
+            array = list(array)
+        elif not isinstance(array, list):
+            raise TypeError(
+                "binary_search_insert() only accepts either a list, range or str"
+            )
+
+        low = 0
+        high = len(array) - 1
+
+        while low <= high:
+            mid = (low + high) // 2
+            if array[mid] == index:
+                # If the item already exists in the array,
+                # insert it after the existing item
+                array.insert(mid + 1, index)
+                return array
+            elif array[mid] < index:
+                low = mid + 1
+            else:
+                high = mid - 1
+
+        # If the item doesn't exist in the array, insert it at the appropriate position
+        array.insert(low, index)
+        return array
+
+    def change(self, index: int, number: int) -> None:
+        """
+        Changes (sets) the index as number
+
+        >>> cont = NumberContainer()
+        >>> cont.change(0, 10)
+        >>> cont.change(0, 20)
+        >>> cont.change(-13, 20)
+        >>> cont.change(-100030, 20032903290)
+        """
+        # Remove previous index
+        if index in self.indexmap:
+            n = self.indexmap[index]
+            if len(self.numbermap[n]) == 1:
+                del self.numbermap[n]
+            else:
+                self.numbermap[n] = self.binary_search_delete(self.numbermap[n], index)
+
+        # Set new index
+        self.indexmap[index] = number
+
+        # Number not seen before or empty so insert number value
+        if number not in self.numbermap:
+            self.numbermap[number] = [index]
+
+        # Here we need to perform a binary search insertion in order to insert
+        # The item in the correct place
+        else:
+            self.numbermap[number] = self.binary_search_insert(
+                self.numbermap[number], index
+            )
+
+    def find(self, number: int) -> int:
+        """
+        Returns the smallest index where the number is.
+
+        >>> cont = NumberContainer()
+        >>> cont.find(10)
+        -1
+        >>> cont.change(0, 10)
+        >>> cont.find(10)
+        0
+        >>> cont.change(0, 20)
+        >>> cont.find(10)
+        -1
+        >>> cont.find(20)
+        0
+        """
+        # Simply return the 0th index (smallest) of the indexes found (or -1)
+        return self.numbermap.get(number, [-1])[0]
+
+
+if __name__ == "__main__":
+    import doctest
+
+    doctest.testmod()

### Describe your change:
Implements a number container system algorithm which stores indexes and numbers at these corresponding indexes.


* [x] Add an algorithm?
* [ ] Fix a bug or typo in an existing algorithm?
* [ ] Documentation change?

### Checklist:
* [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md).
* [x] This pull request is all my own work -- I have not plagiarized.
* [x] I know that pull requests will not be merged if they fail the automated tests.
* [x] This PR only changes one algorithm file.  To ease review, please open separate PRs for separate algorithms.
* [x] All new Python files are placed inside an existing directory.
* [x] All filenames are in all lowercase characters with no spaces or dashes.
* [x] All functions and variable names follow Python naming conventions.
* [x] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html).
* [x] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing.
* [x] All new algorithms include at least one URL that points to Wikipedia or another similar explanation.
* [x] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`.
