Tag
前缀和、Math
题目描述
给你一个下标从 0 开始、由 n 个整数组成的数组 arr 。
arr 中两个元素的 间隔 定义为它们下标之间的 绝对差 。更正式地,arr[i] 和 arr[j] 之间的间隔是 |i - j| 。
返回一个长度为 n 的数组 intervals ,其中 intervals[i] 是 arr[i] 和 arr 中每个相同元素(与 arr[i] 的值相同)的 间隔之和 。
注意:|x| 是 x 的绝对值。
思路分析
- 首先要自己抽象数学公式
- 对绝对值求和要分类讨论,提前求好总距离所涉及到的当前位元素之前的数据下标之和、之后的数据下标之和、前缀和、后缀和(利用总和和前缀和相结合求得)
- 时刻注意 long long
代码如下
#define inter(i) for(int i=0;i<N;i++)
#define interS(i,t) for(auto &i:t)
class Solution {
public:
vector<long long> v;
vector<long long> getDistances(vector<int>& arr) {
map<int,vector<int>> mp; //the same value vs the index of them
map<int,vector<long long>> cnt; //the index and the previous total number 、the forward total number 、前缀和、后缀和
map<int,long long> s; //the total sum count of the same value
int N=arr.size();
inter(i){
mp[arr[i]].push_back(i);
s[arr[i]]+=i;
}
interS(i,mp){
int pre=0;
long long sum=0;
interS(j,i.second){
int n=mp[i.first].size();
cnt[j].push_back(pre);
cnt[j].push_back(n-pre-1);
cnt[j].push_back(sum);
cnt[j].push_back(s[i.first]-sum-j);
sum+=j;
pre++;
}
}
inter(j)
v.push_back((cnt[j][0]-cnt[j][1])*j-cnt[j][2]+cnt[j][3]);
return v;
}
};