Force buckle: 5965 Sum of intervals of the same elements - prefix and

Posted by Parody on Sun, 26 Dec 2021 13:57:39 +0100

Title:

Give you an array arr of n integers with subscripts starting from 0.
The interval between two elements in arr is defined as the absolute difference between their subscripts. More formally, the interval between arr[i] and arr[j] is | i - j |.
Returns an array of intervals of length n, where intervals[i] is the sum of the intervals between arr[i] and each same element in arr (the same value as arr[i]).
Note: | x | is the absolute value of X.

Example 1:

Input: arr = [2,1,3,1,2,3,3]
Output: [4,2,7,2,4,4,5]
Explanation:
Subscript 0: the other 2 is subscript 4, |0 - 4| = 4
Subscript 1: another 1 is in subscript 3, |1 - 3| = 2
Subscript 2: the other two 3 are subscripts 5 and 6, | 2 - 5| + | 2 - 6| = 7
Subscript 3: another 1 is subscript 1, |3 - 1| = 2
Subscript 4: another 2 is subscript 0, |4 - 0| = 4
Subscript 5: the other two 3 are subscripts 2 and 6, | 5 - 2| + | 5 - 6| = 4
Subscript 6: the other two 3 are subscripts 2 and 5, |6 - 2| + |6 - 5| = 5

Example 2:

Input: arr = [10,5,10,10]
Output: [5,0,3,4]
Explanation:
Subscript 0: the other two 10 are subscripts 2 and 3, |0 - 2| + |0 - 3| = 5
Subscript 1: only this 5 is in the array, so the sum of intervals to the same element is 0
Subscript 2: the other two 10 are subscripts 0 and 3, |2 - 0| + |2 - 3| = 3
Subscript 3: the other two 10 are subscripts 0 and 2, | 3 - 0| + | 3 - 2| = 4

Experience: this problem has been worked out through many iterations. The first two times are timeout

The first thought: I thought it was not easy. Two for loops were traversed (one before and one after). When the numbers were equal, the calculated distance was added to the corresponding answer array. There was less code and no unexpected timeout!

class Solution {
public:
    vector<long long> getDistances(vector<int>& arr) {
        int size=arr.size();
        vector<long long>res(size);
        for(int i=0;i<size-1;i++){
            for(int j=i+1;j<size;j++){
                if(arr[i]==arr[j]){//When the numbers are equal
                    int mid=j-i;
                    res[i]+=mid;
                    res[j]+=mid;
                }
            }
        }
        return res;
    }
};

Second thought: obviously, there were a lot of unnecessary calculations last time. Then you can use the map container to put the subscript of the same number in a vector container. When you encounter the same number, you will update the distance to all the current numbers. In this way, it is equivalent to taking out the same number for calculation alone. There is no redundant calculation. I thought it could pass, but it still timed out! Because the distance calculation between the same numbers can also be simplified, that is, prefix and.

class Solution {
public:
    
    vector<long long> getDistances(vector<int>& arr) {
        int size=arr.size();
        vector<long long>res(size);
        map<int,vector<int>> map_n;//Load the same value into the map
        
        for(int i=0;i<size;i++){
            int m_size=map_n[arr[i]].size();
            if(m_size!=0){
                for(int j=0;j<m_size;j++){
                    int mid=i-map_n[arr[i]][j];
                    res[i]+=mid;
                    res[map_n[arr[i]][j]]+=mid;
                }
            }
            map_n[arr[i]].push_back(i);
        }
        return res;
    }
};

The third time: of course, this time I saw the big guys' solutions. I didn't think about it.
Specific idea: prefix and can be: prenum[i] = prenum[pro] corresponding to the same value as arr[i] + the distance from the previous one to the current one × number. (you can draw and understand by yourself)
Then the distance of this number is actually the sum of the prefix before the number and the suffix after the number, so we can find the prefix sum and the suffix sum and add it.

class Solution {
public:
    vector<long long> getDistances(vector<int>& arr) {
        int size=arr.size();
        vector<long long>res(size);
        map<int,vector<int>> map_n;
        map<int,long long> prenum;//Prefix and
        map<int,long long> nxtnum;//Suffix and

        for(int i=0;i<size;i++){//Add elements to the map for classification
            map_n[arr[i]].push_back(i);
        }
        //Prefix and suffix each same element
        for(auto it=map_n.begin();it!=map_n.end();it++){
            auto &v=it->second;
            int v_size=v.size();
            prenum[v[0]]=0;
            for(int i=1;i<v_size;i++){
                prenum[v[i]]=prenum[v[i-1]]+i*(v[i]-v[i-1]);
            }
            nxtnum[v[v_size-1]]=0;
            for(int i=v_size-2;i>=0;i--){
                nxtnum[v[i]]=nxtnum[v[i+1]]+(v_size-1-i)*(v[i+1]-v[i]);
            }
        }
        //Get results
        for(int i=0;i<size;i++){
            res[i]+=prenum[i];
            res[i]+=nxtnum[i];
        }
        return res;
    }
};

Topics: Algorithm leetcode