Data structure brushing questions: day 15 (basic)

 

Table of contents

One, a number that appears only once

1, bit operation

Complexity Analysis

Second, most elements

1. Hash table

train of thought

algorithm

Complexity Analysis

2. Sort

train of thought

algorithm

Complexity Analysis

3. Randomization

train of thought

algorithm

three, the sum of three numbers

One, a number that appears only once

136. Numbers that appear only once - LeetCode https://leetcode.cn/problems/single-number/?envType=study-plan&id=shu-ju-jie-gou-ji-chu

1, bit operation

If the constraints of time complexity and space complexity are not considered, there are many solutions to this problem, and the possible solutions are as follows.

Use sets to store numbers. Traverse each number in the array, if the number does not exist in the set, add the number to the set, if the number already exists in the set, delete the number from the set, and the last remaining number is the number that appears only once .

Use a hash table to store each number and the number of times that number occurs. By traversing the array, you can get the number of occurrences of each number, and update the hash table, and finally traverse the hash table to get the number that only appears once.

Use a set to store all the numbers that occur in the array, and calculate the sum of the elements in the array. Since the set guarantees no duplicate elements, the sum of all elements in the set is calculated twice, which is the sum of the elements in the case where each element appears twice. Since only one element in the array appears once, and the rest of the elements appear twice, the sum of the elements in the array is subtracted from twice the sum of the elements in the set, and the remaining number is the number that appears only once in the array.

All three solutions above require additional space usage of O(n), where n is the length of the array.

How can we achieve linear time complexity and constant space complexity?

The answer is to use bitwise operations. For this problem, the XOR operation ⊕ can be used. XOR operation has the following three properties.

Do XOR operation between any number and 0, the result is still the original number, that is a⊕0=a.
Any number is XORed with itself, and the result is 0, that is, a⊕a=0.
XOR operation satisfies commutative law and associative law, that is, a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b.

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (auto e: nums) ret ^= e;
        return ret;
    }
};

Complexity Analysis

  • Time complexity: O(n), where nn is the array length. You only need to iterate over the array once.

  • Space complexity: O(1).

Second, most elements

169. Majority Elements - LeetCode https://leetcode.cn/problems/majority-element/?plan=data-structures&plan_progress=zz5yyb3

Explanation
The simplest brute force method is to enumerate each element in the array, and then traverse the array to count the number of occurrences. The time complexity of this method is O(n^2), which will exceed the time limit, so we need to find an excellent practice with a time complexity less than O(n^2).

1. Hash table

train of thought

We know that the element with the most occurrences is greater than n/2 times, so a hash table can be used to quickly count the number of occurrences of each element.

algorithm

We use a hash map (HashMap) to store each element and the number of occurrences. For each key-value pair in a hash map, the key represents an element and the value represents the number of occurrences of that element.

We use a loop to traverse the array nums and add each element in the array to the hash map. After this, we iterate over all key-value pairs in the hash map and return the key with the largest value. We can also use the method of fighting when traversing the array nums to maintain the maximum value, which saves the final traversal of the hash map.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> counts;
        int majority = 0, cnt = 0;
        for (int num: nums) {
            ++counts[num];
            if (counts[num] > cnt) {
                majority = num;
                cnt = counts[num];
            }
        }
        return majority;
    }
};

Complexity Analysis

Time complexity: O(n), where n is the length of the array nums. We iterate through the array nums once, and for each element in nums, it takes constant time to insert it into the hash table. If the maximum value is not maintained during traversal, the hash table needs to be traversed after the traversal, because the space occupied by the hash table is O(n) (refer to the space complexity analysis below), then the traversal time Will not exceed O(n). So the total time complexity is O(n).

Space complexity: O(n).

2. Sort


train of thought

If all the elements in the array nums are sorted in monotonically increasing or monotonically decreasing order, then the element with subscript n/2 (subscript starts from 0) must be the majority.

algorithm

For this algorithm, we first sort the nums array, and then return the element corresponding to the subscript mentioned above. The diagram below explains why this strategy works. In the figure below, the first example is the case where n is odd and the second example is the case when n is even.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() / 2];
    }
};

Complexity Analysis

Time complexity: O(nlogn). The time complexity of sorting an array is O(nlogn).

Space complexity: O(logn). If you use the sorting algorithm that comes with the language, you need to use O(logn) stack space. If you write your own heapsort, you only need to use O(1) extra space.

3. Randomization


train of thought

Because more than n/2 array subscripts are occupied by the mode, we randomly select an element corresponding to the subscript and verify that there is a high probability that the mode can be found.

algorithm

Since the number corresponding to a given subscript is likely to be the majority, we randomly pick a subscript, check whether it is the majority, and return if it is, otherwise continue to pick randomly.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        while (true) {
            int candidate = nums[rand() % nums.size()];
            int count = 0;
            for (int num : nums)
                if (num == candidate)
                    ++count;
            if (count > nums.size() / 2)
                return candidate;
        }
        return -1;
    }
};

Look at the solution:

Majority Element - Majority Element - LeetCode https://leetcode.cn/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/

three, the sum of three numbers

15. The sum of three numbers - LeetCode https://leetcode.cn/problems/3sum/?plan=data-structures&plan_progress=zz5yyb3

 Look at the solution:

Sum of Three Numbers - Sum of Three Numbers - LeetCode https://leetcode.cn/problems/3sum/solution/san-shu-zhi-he-by-leetcode-solution/

Guess you like

Origin blog.csdn.net/m0_63309778/article/details/126844538