task 01 array -- datawhale and Tianchi

Posted by FD_F on Tue, 15 Feb 2022 17:29:43 +0100

task 01 array - datawhale and Tianchi

Example analysis

1. Sum of two numbers

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        for (int i = 0 ; i < n - 1; ++ i)
            for (int j  = i + 1; j < n ;++ j)
            {
                if (nums[i] + nums[j] == target) return {i,j};
               
            }
            return {};
    }
};

Algorithm idea:

For a simple violent search, first use the first number and then match the following numbers in turn. If no result is found after a round of traversal, then use the second number to match the numbers after the second number in turn, and so on. Its time complexity is O ( n 2 ) O(n^2) O(n2), you can reduce the time complexity through the hash table, but talk about it when the task comes to the hash!

2. The sum of the nearest three numbers

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int n = nums.size();
        int ans = nums[0]+nums[1]+nums[2];
        for (int i = 0 ; i < n - 2 ; ++ i)
            for (int j = i + 1; j < n - 1 ; ++ j)
                for (int k = j + 1; k < n ; ++ k)
                {
                    int temp = nums[i] + nums[j] + nums[k];
                    if (abs(temp - target) < abs (ans - target)) ans = temp;
                }
        return ans;
    }
};

The first method is the algorithm idea:

The violent search method is the sum of the two above, but its time complexity is O ( n 3 ) O(n^3) O(n3). When the use case is large, the code execution will timeout, so it is not recommended.

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int ans = nums[0] + nums[1] + nums[2];
        int n = nums.size();
        for (int i = 0 ; i < n - 2 ; ++ i)
        {
            int start = i + 1,end = n - 1;
            while (start < end)
            {
                int temp = nums[start] + nums[end] + nums[i];
                if (abs(temp - target) < abs(ans - target)) ans = temp;
                if (temp > target) --end;
                else if (temp < target) ++start;
                else return ans;
            }
        }
        return ans;
    }
};

The second method is the algorithm idea:

Sort + double pointer. First sort the array to make it orderly, and then optimize the matching process with the help of double pointers. In terms of image, an array with size n is divided into two arrays, one with size 1 and one with size n-1. First put the minimum value of the array into the first array, then put the remaining number into another array, and then take the value of the first array and the maximum and minimum values of the second array to match the second array, If the sum of the three numbers is greater than the target, update the value of the maximum value by one digit. If the sum of the three numbers is less than the target, update the value of the minimum value by one digit. Stop matching until the minimum value is equal to the maximum value, and then reallocate the two arrays. The first array takes the second number, and the remaining number is added to the second array, and so on. The time complexity of this algorithm is O ( n 2 ) O(n^2) O(n2)

After class exercises

1. Remove elements

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
        int count = 0;
        for (int i = 0 ; i < n ; ++ i )
        {
            if (nums[i] != val)
            {
                nums[count] = nums[i];
                ++ count;
            }
        }
        return count;
    }
};

The first method is the algorithm idea:

Simple question violence search. Judge each number of the array in sequence. If it is not stored in front of the array and counted, the count value and the count value before the array will be output at last. Its time complexity is O ( n ) O(n) O(n)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int left = 0 , right = nums.size();
        while (left < right)
        {
            if (nums[left] == val) nums[left] = nums[--right];
            else ++left;
        }    
        return left;
    }   
};

The second method is the algorithm idea:

Double pointer. Because the array element value is variable and only the valid part in front of the element is displayed, you can use double pointers to reduce some unnecessary repeated assignments. The left pointer points to the first number of the array and the right pointer points to the last number of the array. Compare the number pointed by the left pointer. If it is equal to val, assign the number pointed by the right pointer to the number of left pointers, and then move the right pointer to the left to continue comparing the number of left pointers. If it is not equal to val, move the left pointer to the right until the two pointers coincide. Its time complexity is O ( n ) O(n) O(n), but optimized.

2. Delete duplicates in the ordered array

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n = nums.size();
        if ( n == 0 ) return 0;
        int count = 1;
        int temp = nums[0];
        for (int i = 1 ; i < n ; ++ i)
        {
            if (nums[i] != temp)
            {
                nums[count] =nums[i];
                ++ count;
                temp = nums[i];
            }
        }
        return count;
    }
};

The first method is the algorithm idea:

Double pointer. It looks like the above question. The burst search is actually a double pointer. The fast and slow pointer is used. The slow pointer finally points to the last position of the effective part, and the fast pointer is used for traversal. Its time complexity is O ( n ) O(n) O(n)

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n = nums.size();
        if ( n == 0 ) return 0;
        int fast = 1, slow = 1;
        while (fast < n)
        {
            if (nums[fast] != nums[fast - 1])
            {
                nums[slow] = nums[fast];
                ++ slow;
            }
            ++ fast;
        }
        return slow;
    }
};

The second method is the algorithm idea:

Double pointer. The same double pointer method seems to be the standard double pointer writing method, but in fact, it is different from the first method in comparison and judgment. The first method is to compare the first value of each different number saved by the variable when the fast pointer is traversed, while the second method is to compare two adjacent numbers, The relationship between the two is that when the pointer moves slowly, the former finds that the first value of the latter number is different from the previous one, and the latter finds that the last value of the latter number is different from the previous one. Its time complexity is O ( n ) O(n) O(n)

3. Sum of three numbers

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>> ans;
        if (n < 3 || nums[0] > 0 || nums[n-1] < 0) return ans;
        for (int i = 0 ; i < n - 2; ++ i)
        {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int start = i + 1, end = n - 1;
            while (start < end)
            {
                int temp = nums[start] + nums[end] + nums[i];
                if (temp == 0){
                    ans.push_back({nums[start],nums[end],nums[i]});
                    while (start < end && nums[start] == nums[start + 1]) ++ start;
                    while (start < end && nums[end] == nums[end - 1]) -- end;
                    ++ start;
                    -- end;
                }else if (temp > 0) --end;
                else ++ start;
            }
        }
        return ans;
    }
};

Algorithm idea:

Sort + double pointer. In fact, it is similar to the example, but the only trouble is that we can't repeat triples, so we have to find a way to eliminate duplicates. First, we think of three empty returns: first, the array size is less than three and can't form a triplet. Second, the minimum value of the array is greater than 0. Obviously, the sum of three numbers can't be equal to 0. Third, The maximum value of the array is less than 0, and the sum of three numbers cannot be equal to 0 Then we use the double pointer to divide the minimum and maximum of the first number, judge whether the addition of three values is equal to 0, record the triplet, and then compare whether the left pointer is equal to its subsequent value, move the left pointer to the right, compare whether the right pointer is equal to its subsequent value, and move the right pointer to the left until it is unequal (this method is to reduce repeated triples), And so on. Its time complexity is O ( n ) O(n) O(n).

summary

Familiar with the array and simple double pointer problem, I hope to make persistent efforts~

Topics: Algorithm data structure leetcode