Skip to content

Commit

Permalink
feat(arrays): intersection of two arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianLusina committed Jun 18, 2024
1 parent fcc5584 commit 9cb1302
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 98 deletions.
50 changes: 49 additions & 1 deletion algorithms/arrays/intersection/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Intersection between arrays
# Intersection of Two Arrays

Find the intersection between 2 arrays and return the values that intersect in a new array.
An intersection is a list of all the values that occur in both of the arrays.
Expand All @@ -10,3 +10,51 @@ a = [3,1,4,2]
b = [4,5,3,6]
intersection = [3,4]
```

---
## Intersection of Two Arrays I

Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear
as many times as it shows in both arrays and you may return the result in any order.

```text
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
```

```text
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [4,9]
Explanation: [9,4] is also accepted.
```

Follow up:

- What if the given array is already sorted? How would you optimize your algorithm?
- What if nums1's size is small compared to nums2's size? Which algorithm is better?
- What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into
the memory at once?

## Intersection of Two Arrays II

Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear
as many times as it shows in both arrays and you may return the result in any order.

```text
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
```

```text
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [4,9]
Explanation: [9,4] is also accepted.
```
9 changes: 5 additions & 4 deletions algorithms/arrays/intersection/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ def intersection(a: List[T], b: List[T]) -> List[T]:
Space Complexity:
Again, this will depend on the sizes of each list, but it averages to O(N+M) where N is the size of the first
list and M is the size of the second list
:param a: first collection
:param b: second collection
:return: list of all values that intersect between the 2 collections
Args:
a list: first collection
b list: second collectoin
Returns:
list: all values that intersect between the 2 collections
>>> a1 = [3,1,4,2]
>>> b1 = [4,5,3,6]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
from typing import List
from typing import List, TypeVar, Set

T = TypeVar("T")

def set_intersection(set1, set2):

def set_intersection(set1: Set[T], set2: Set[T]) -> List[T]:
return [x for x in set1 if x in set2]


def intersection(nums1: List[int], nums2: List[int]) -> List[int]:
def intersection(list_one: List[T], list_two: List[T]) -> List[T]:
"""
Returns the intersection of two arrays. Uses a set to solve the problem in linear time. A set provides in/contains
operation in O(1) time in average case. This converts both arrays to sets and iterates over the smallest set
checking the presence of each element in the other larger set. The time complexity is O(n+m) where n is the size of
the first array and m is the size of the second array.
@param nums1: 1st Array of numbers
@param nums2: 2nd Array of numbers
@return: Returns the intersection of the two arrays
@rtype: List[int]
Args:
list_one list: 1st Array of items
list_two list: 2nd Array of items
Returns:
list: the intersection of the two arrays
"""
set1 = set(nums1)
set2 = set(nums2)
set1 = set(list_one)
set2 = set(list_two)

if len(set1) < len(set2):
return set_intersection(set1, set2)
Expand Down
42 changes: 42 additions & 0 deletions algorithms/arrays/intersection/intersection_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from typing import List, TypeVar

T = TypeVar("T")


def intersect(list_one: List[T], list_two: List[T], include_duplicates: bool = True) -> List[T]:
"""
Given two arrays, find their intersection. This assumes that the lists are not sorted. First sorting takes place
on both lists which will incur a cost of O(nlog(n)) + O(mlog(m)) depending on the algorithm used. Time will also
include iterating over both lists which will be O(n+m) where n is the size of list one and m is the size of list two
Next 2 pointers are set to be used to keep track of which element we are on in the iteration of both lists.
As long as both pointers are less than their respective lists, we compare each element to each other. If the element
from the first collection/list is less than an element from the second collection, we move the first pointer a step
forward, otherwise we move the second pointer.
In the event, they are equal to each other, it means there is an intersection. At this point we check if the
include_duplicates argument is true and include the first element. If it is set to false, we check if the preceding
element from the first list is not equal to the current element and include it, this removes duplicates.
Afterwards, we move the pointers forward.
Space Complexity results in O(n+m) were n is the size of list one and m is the size of list two. This is because
the elements are stored in a resulting list which is returned as the result of this function.
"""
sorted_list_one, sorted_list_two, result = sorted(list_one), sorted(list_two), []
pointer_one, pointer_two = 0, 0

while pointer_one < len(sorted_list_one) and pointer_two < len(sorted_list_two):
first_element = sorted_list_one[pointer_one]
second_element = sorted_list_two[pointer_two]

if first_element < second_element:
pointer_one += 1
elif second_element < first_element:
pointer_two += 1
else:
if include_duplicates:
result.append(first_element)
else:
if pointer_one == 0 or first_element != sorted_list_one[pointer_one - 1]:
result.append(first_element)
pointer_one += 1
pointer_two += 1
return result
8 changes: 8 additions & 0 deletions algorithms/arrays/intersection/test_intersection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ def test_1(self):
actual = intersection(a, b)
self.assertEqual(expected, actual)

def test_2(self):
"""should return [3,7] for a = [2,3,3,5,7,11], b = [3,3,7,15,31]"""
a = [2, 3, 3, 5, 7, 11]
b = [3, 3, 7, 15, 31]
expected = [3, 3, 7]
actual = intersection(a, b)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from datastructures.arrays.intersection_of_two_arrays.intersection_one import (
from algorithms.arrays.intersection.intersection_one import (
intersection,
)

Expand All @@ -20,6 +20,14 @@ def test_4_9_5_and_9_4_9_8_4(self):
actual = intersection(nums1, nums2)
self.assertEqual(actual, expected)

def test_2(self):
"""should return [3,7] for a = [2,3,3,5,7,11], b = [3,3,7,15,31]"""
a = [2, 3, 3, 5, 7, 11]
b = [3, 3, 7, 15, 31]
expected = [3, 7]
actual = intersection(a, b)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
39 changes: 39 additions & 0 deletions algorithms/arrays/intersection/test_intersection_two.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import unittest

from algorithms.arrays.intersection.intersection_two import intersect


class IntersectionTwoTestCase(unittest.TestCase):
def test_1_2_2_1_and_2_2_returns_2_2(self):
"""Should return [2, 2] for nums1=[1,2,2,1] and nums2=[2,2]"""
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
expected = [2, 2]
self.assertEqual(intersect(nums1, nums2), expected)

def test_4_9_5_and_9_4_9_8_4_returns_4_9(self):
"""Should return [4, 9] for nums1=[4,9,5] and nums2=[9,4,9,8,4]"""
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
expected = [4, 9]
self.assertEqual(intersect(nums1, nums2), expected)

def test_2(self):
"""should return [3,3,7] for a = [2,3,3,5,7,11], b = [3,3,7,15,31]"""
a = [2, 3, 3, 5, 7, 11]
b = [3, 3, 7, 15, 31]
expected = [3, 3, 7]
actual = intersect(a, b)
self.assertEqual(expected, actual)

def test_2_remove_duplicates(self):
"""should return [3,7] for a = [2,3,3,5,7,11], b = [3,3,7,15,31] without including duplicates"""
a = [2, 3, 3, 5, 7, 11]
b = [3, 3, 7, 15, 31]
expected = [3, 7]
actual = intersect(a, b, include_duplicates=False)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
40 changes: 0 additions & 40 deletions datastructures/arrays/intersection_of_two_arrays/README.md

This file was deleted.

This file was deleted.

23 changes: 0 additions & 23 deletions tests/datastructures/arrays/test_intersection_two.py

This file was deleted.

0 comments on commit 9cb1302

Please sign in to comment.