[resolve data structure] explain the set structure in detail and implement a set

Posted by bcoffin on Mon, 22 Nov 2021 12:40:27 +0100

📢 Hello, I'm Xiaocheng, a sophomore front-end enthusiast

📢 This article will explain collections in data structures

📢 Thank you very much for reading. You are welcome to correct the wrong places 🙏

📢 May you be loyal to yourself and love life

💡 First look at knowledge points

  • What is a collection?
  • What methods do collections have
  • Implement a collection
  • How do collections operate
  • LeetCode actual combat

📢 Broken thoughts

In the previous article, we learned three kinds of linear structures. Next, we need to learn the set. I prefer to call it a container. It has very powerful methods and efficiency. Let's learn together~

1, What is a collection?

Set is composed of a group of unordered and unique (i.e. non repeatable) items. It has the property of finite set in mathematics.

In mathematics, a set is a set of different objects, such as:

Set of natural numbers: N = {0, 1, 2, 3, 4, 5, 6,...}. The objects in the set are surrounded by curly braces

The above figure can represent a set with uniqueness and disorder

Next, let's implement a collection~

2, What are the methods of collection?

A Set class is added in ES6, which can be used to quickly create a Set. Here we implement a Set class ourselves

As we mentioned above, we use an object to create a collection (or an array)

Of course, it is more convenient to select objects to create. In JavaScript objects, one key is not allowed to point to two different attributes, which ensures that the elements in the collection are unique

Here we need to add these methods to the collection

methodmeaning
add(value)Adds a new element to the collection
remove(value)Remove a value from the collection
has(value)Determine whether a value exists in the set
clear()Empty collection
size()Returns the number of elements in the collection
values()Returns an array of all values in the collection

3, Handwriting implements a collection

1. Create a Set class

Use objects to create a collection

class Set {
    constructor () {
        this.data = {}
    }
}

Next, start the encapsulation method

2. Implement has method

Before implementing the add method, you need to implement a has method

has(value) {
    return value in this.data
}

Here, we use the in operator to judge whether value exists in the data object. If so, we can return true

3. Implement the add method

Due to the uniqueness of the collection, we need to judge whether there is a current element in the current collection before adding an element. If it does not exist, it will be added to the collection and return true successfully. If it exists, it will return false and not added

add(value) {
    if(!this.has(value)) {
        this.data[value] = value
        return true
    }
    return false
}

Here, we first judge whether there is a value through the has method, and if not, add it to the collection

4. Implement the remove method

The remove method removes an element from the collection and accepts the element to be removed as a parameter

remove (value) {
    if(this.has(value)) {
        delete this.data[value]
        return true
    }
    console.log('The element to be deleted was not found');
    return false
}

Here, first judge whether there is this value through the has method. If there is any, delete is used to delete the element without prompting that it is not found

5. Implement the clear method

The clear method empties the entire collection. We can also reset the object

clear() {
    this.data = {}
}

6. Implementation method

There are many ways to implement size

First kind

You can use the built-in method keys of the object class, which can return an array of all attributes of a given object

Therefore, we can use the length method to obtain its length

size() {
    return Object.keys(this.data).length
}

Second

We can manually extract each attribute on the data object and record the number of attributes

size() {
    let count = 0;
    // Traversal object
    for(let prop in this.data) {
        if(this.data.hasOwnProperty(prop)) {
            ++count
        }
    }
    return count
}

Here, we also need to use the hasOwnProperty method of the object to determine whether this property is a method on the prototype, because the object contains many built-in methods. When traversing with for in, we will traverse values that are not in the collection

Simply use the first method

7. values method

We need to convert the data set into an array. We can use the keys method used before

values() {
    return Object.keys(this.data)
}

8. Complete Set implementation

class Set {
    constructor() {
        this.data = {}
    }
    has(value) {
        return value in this.data
    }
    add(value) {
        if (!this.has(value)) {
            this.data[value] = value
            return true
        }
        return false
    }
    remove(value) {
        if (this.has(value)) {
            delete this.data[value]
            return true
        }
        console.log('The element to be deleted was not found');
        return false
    }
    clear() {
        this.data = {}
    }
    size() {
        return Object.keys(this.data).length
    }
    values() {
        return Object.keys(this.data)
    }
}

9. How to use the Set method

We only need to construct an instance object through the new method to operate it

const set = new Set()

Add element

set.add(2)
set.add(3)

Delete element

set.remove(3)
set.remove(4) // The element to be deleted was not found

4, Collection operation method

In mathematics, we often do some operations of finding, intersection, union, subset and difference set, which can also be realized here

methodmeaning
union()Union
intersection()intersection
difference()Difference set
subset()Difference set

1. Realize union operation

Union set is a collection of given two sets, that is, a new set composed of all elements

How

  1. First, we need to receive an incoming set otherSet and create a new set to store the last data
  2. Expand the collection into an array through the values method, traverse and add it to the new collection, and the same is true for the incoming array
  3. Finally, a new set is returned

Note: since we do not reserve parameters when encapsulating values, we need to use otherSet.values when transforming otherSet

union(otherSet) {
    const unionSet = new Set()
    // Collection - > array
    const values = this.values()
    const values2 = otherSet.values(otherSet)
    values.map(item => { unionSet.add(item) })
    values2.map(item => { unionSet.add(item) })
    return unionSet
}

How to use it?

const set = new Set()
const set2 = new Set()
set2.add(3)
set.add(2)
console.log(set.union(set2)); // Set { data: { '2': '2', '3': '3' } }

2. Realize intersection operation

Intersection operation is to return a new set composed of the same elements in two sets

Realization idea

  1. Create a new collection to be returned and receive a collection at the same time
  2. The same is converted to an array for operation
  3. Take a set to traverse, and use has to judge whether there is this value in another set. If so, it indicates that it is public and added to the new set

Do you know the time complexity of this implementation?

intersection() {
    const intersectionSet = new Set()
    // Convert current collection to array
    const values = this.values()
    for (let i = 0; i < values.length; i++) {
        if (otherSet.has(values[i])) {
            intersectionSet.add(values[i])
        }
    }
    return intersectionSet

3. Implement difference set operation

The difference set operation is to return relatively different parts. The difference sets of a and B are the separate parts of A

The blue one is what we asked for

The implementation idea is the opposite of union

difference(otherSet) {
    const differenceSet = new Set()
    const values = this.values
    for (let i = 0; i < values.length; i++) {
        // Judge whether there is this element in the otherSet, and no is the difference part
        if (!otherSet.has(values[i])) {
            differenceSet.add(values[i])
        }
    }
    return differenceSet
}

4. Implement subset method

Subsets are used to determine whether they are parent-child relationships, that is, whether set A is included in set B

Realization idea

  • If the size of A set is larger than that of B set, it cannot be A subset
  • Judge whether all elements in set A can be found in set B
subset(otherSet) {
    if (this.size() > otherSet.size()) {
        return false
    }
    // return interrupt
    let values = this.values()
    for(let i = 0;i<values.length;i++) {
        if(!otherSet.has(values[i])) {
            return false
        }
    }
    return true
}

Until now! Finally, these methods have been realized. In fact, the ideas are similar. Thank you very much for seeing here. Thank you~

5, LeetCode actual combat

349. Intersection of two arrays

Given two arrays, write a function to calculate their intersection.

Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]

When LeetCode brushes questions, we don't need to implement a collection ourselves. We can directly use the ready-made Set class to create a collection

AC elegant code

var intersection = function (nums1, nums2) {
    // De duplication of nums1
    const set1 = new Set(nums1)
    const set2 = new Set(nums2)
    return [...new Set([...set1].filter(item => set2.has(item)))]
};

It may be different from the methods mentioned above, because there are a large number of API s in the array for us to use. We need to be able to make choices for different scenarios

📖 summary

In this article, we encapsulate a collection and implement many collection operation methods at the same time.

The Set class is added in ES6. Its bottom layer is implemented through map. The bottom layer of map is implemented by hash table. It greatly optimizes the speed of our value checking. Therefore, when brushing questions, you can think about whether you can use Set to implement it.

That's the end of this article. I'm sure you can learn a lot from it. The next article will take you to explore the mysteries of the dictionary.

Welcome to this column and continue to pay attention to the latest articles~

Other contents of this column

Start here 👉 [resolve data structure] start the data structure and algorithm here

Stack 👉 [resolve data structure] what is stack? Handwriting to achieve a stack structure!

Queue 👉 [resolve data structure] explain the queue, priority queue and circular queue in detail, and implement a queue

Finally, it may not be clear enough in many places. Please forgive me

💌 If there are any mistakes or questions in the article, you are welcome to leave a message and exchange private messages

Topics: Javascript Front-end React data structure leetcode