知识点:哈希
设 count[i] 为数字 i 出现的次数,则答案为 count[i]*(count[i]-1)/2 的累加和,i ∈ [1, 100]。
首先遍历 nums 统计每个数字出现的次数,然后遍历 count 计算答案即可。
class Solution {
public:
int numIdenticalPairs(vector<int>& nums) {
int count[101] = {0};
for(auto v : nums) {
count[v]++;
}
int anw = 0;
for(int i = 1; i <= 100; i++) {
anw += count[i]*(count[i]-1)/2;
}
return anw;
}
};
知识点:双指针
初始时,两个指针 head,tail 都指向 -1 位置。
不停的移动两个指针,直到 tail 指向最后一个字符,每轮移动规则如下:
class Solution {
public:
int numSub(string s) {
int64_t count = 0;
for(int prefix = -1, i = 0, n = s.size(); i < n; i++) {
if(s[i] == '0') {
prefix = i;
} else {
count += i-prefix;
count %= 1000000007;
}
}
return count;
}
};
知识点:最短路
典型的最短路问题。只不过路径的权值的计算方式从加法变成了乘法,从最近变成了求最大。但只要不会出现"负环",即存在有限长度的最优路径,我们就可以借助优先队列+BFS搞定。
Q: 啥情况会出现负环?
A: 比如求权值最小的路径时,存在权值为负的边。只要不停的走这条负边,路径的权值就会不断减小。此时显然不存在有限长度的最优路径。
class Solution {
public:
vector<pair<double, int>> next[10000];
double prob[10000];
double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
for(int i = 0; i < edges.size(); i++) { // 建立邻接表
int u = edges[i][0];
int v = edges[i][1];
double p = succProb[i];
next[u].push_back(make_pair(p, v));
next[v].push_back(make_pair(p, u));
}
typedef pair<double, int> Data;
priority_queue<Data, vector<Data>, less<Data>> pq; //借助 less 建立大顶堆,优先按概率排序。
memset(prob, 0, sizeof(double)*n);
prob[start] = 1.0; // 自己到自己的概率肯定是 1。
pq.push(make_pair(1.0, start)); // 将起点放入队列。
while(pq.empty() == false) {
auto f = pq.top(); // 从大顶堆中取出当前访问到的概率最大的点。
pq.pop();
if(f.first < prob[f.second]) { // 剪枝
continue;
}
for(auto ne : next[f.second]) { // 从 f 继续向周围走一步。
int next = ne.second; // 下一步可到达的点
double p = prob[f.second] * ne.first; // 计算从 start 经 f 到 next 的概率。
if(p > prob[next]) { // 比之前到达 next 的路径更优。
prob[next] = p; // 更新
// 虽然可能重复同一个点,但上面的剪枝语句保证了只有最大的那个才会生效。
// 而且 if(p > prob[next]) 保证了不可能放入重复的概率。
pq.push(make_pair(p, next));
}
}
}
return prob[end];
}
};
知识点:模拟退火;P-median problem
友情链接:P-中位问题_百度百科 模拟退火_百度百科
平面包含无数个点,而我们要从这无数个点中找到一个最优解,这在大多数情况下是不可能的。我们能做的只能是在精度要求范围能找到一个近似最优解。传统的解决方案就是模拟退火。算法流程如下:
const double eps = 1e-8;
const int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
double calc(double ax, double ay, double bx, double by) {
double dx = bx - ax, dy = by - ay;
return sqrt(dx * dx + dy * dy);
}
class Solution {
public:
double getMinDistSum(vector<vector<int>>& positions) {
int n = positions.size();
double x = 0, y = 0;
auto dist = [&](double cx, double cy) {
double ans = 0;
for (auto v : positions)
ans += calc(cx, cy, v[0], v[1]);
return ans;
};
double d = dist(x, y);
double step = 100.0;
int done = 0;
while (step > eps) {
done = 0;
for (int i = 0; i < 4; ++i) {
double nx = (double)x + step * dx[i];
double ny = (double)y + step * dy[i];
double t = dist(nx, ny);
if (t < d) {
d = t;
x = nx;
y = ny;
done = 1;
break;
}
}
if (!done)
step /= 2;
}
return d;
}
};