前两周期末没空 没做周赛
给你一个整数数组 nums 。
如果一组数字 (i,j) 满足 nums[i] == nums[j] 且 i j ,就可以认为这是一组 好数对 。
返回好数对的数目。
示例 1
输入:nums = [1,2,3,1,1,3]
输出:4
解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始
示例 2
输入:nums = [1,1,1,1]
输出:6
解释:数组中的每组数字都是好数对
示例 3
输入:nums = [1,2,3]
输出:0
提示
按照题目要求进行计数
对于每个i去找和他一样的j 注意ji
一样的话计数就加1
总的时间复杂度是遍历每个i和往后的j 为O(n^2)
class Solution {
public
int numIdenticalPairs(vectorint& nums) {
int ans=0;
for(int i=0;inums.size()-1;i++)
for(int j=i+1;jnums.size();j++)
if(nums[i]==nums[j])ans++;
return ans;
}
};
给你一个二进制字符串 s(仅由 ‘0’ 和 ‘1’ 组成的字符串)。
返回所有字符都为 1 的子字符串的数目。
由于答案可能很大,请你将它对 10^9 + 7 取模后返回。
示例 1
输入:s = 0110111
输出:9
解释:共有 9 个子字符串仅由 ‘1’ 组成
1 - 5 次
11 - 3 次
111 - 1 次
示例 2
输入:s = 101
输出:2
解释:子字符串 1 在 s 中共出现 2 次
示例 3
输入:s = 111111
输出:21
解释:每个子字符串都仅由 ‘1’ 组成
示例 4
输入:s = 000
输出:0
提示
我们来看11011这个串 共有3+3个连续1串
为什么我会用3+3来算呢 因为我是以一个连续1的子串来计数的
没错 这就是子问题 我们再来看一个110111 这个按照我的思想就是3+6
那么这里用0来划分就搞定了
下一个问题在于怎样算出3和6呢
显然 对于一个连续的1串 他的总长为1+2+3+…+length
也就是n(n+1)2 而且这个可以用递推来加
那么总的时间复杂度就是遍历整个字符串的O(n)
class Solution {
public
int ans=0;
const int mod = 1e9+7; 记得取模
int numSub(string s) {
int cnt=0; 可以说是当前的长度 用来算1+2+...+n
for(int i=0;is.size();i++)
{
if(s[i]=='1'){ 连续的1串
cnt=(cnt+1)%mod; 递推增加 也可以用数列求和公式代替
ans=(ans+cnt)%mod;
}
else cnt=0; 0分割开的
}
return ans;
}
};
给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 a 和 b 的一条无向边,且该边遍历成功的概率为 succProb[i] 。
指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。
如果不存在从 start 到 end 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。
示例 1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCOBzdHw-1594541358065)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads202007121558_ex1.png)]
输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
输出:0.25000
解释:从起点到终点有两条路径,其中一条的成功概率为 0.2 ,而另一条为 0.5 0.5 = 0.25
示例 2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SRjf5pZZ-1594541358067)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads202007121558_ex2.png)]
输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
输出:0.30000
示例 3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mTeHREQc-1594541358069)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads202007121558_ex3.png)]
输入:n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
输出:0.00000
解释:节点 0 和 节点 2 之间不存在路径
提示
看上去就是求某个条件下的最优路径
对比最短路的求法的话 单源最短路我们可以用dijkstra来做
再看下题目的复杂度 估计是要用到nlogn堆优化的dijkstra来做的
既然是类最短路模板题 我们先来思考下dijkstra正不正确
那就直接模板干吧 详细看代码比较清晰
总的时间复杂度就是nlogn
class Solution {
public
vectorint e,ne,h; 邻接表的模板
vectordouble w;
int n,m;
int idx=0;
double maxProbability(int N, vectorvectorint& edges, vectordouble& succProb, int start, int end) {
m=2edges.size();
n=N;
e.resize(m+5,0);
w.resize(m+5,0.0);
ne.resize(m+5,0);
h.resize(n+5,-1);
for(int i=0;iedges.size();i++) 先邻接表添加边
{
add(edges[i][0],edges[i][1],succProb[i]);
add(edges[i][1],edges[i][0],succProb[i]);
}
return dijkstra(start,end); 直接跑一次迪杰斯特拉
}
void add(int a,int b,double W) 邻接表加边 我的博客有
{
e[idx]=b;
w[idx]=W;
ne[idx]=h[a];
h[a]=idx++;
}
double dijkstra(int begin,int end) dijk改动下 我的博客也有
{
vectordouble dis(n,0); 初始化为0概率 dis这个名字应该改下
vectorint vis(n,false);
dis[begin]=1; 只有起点是1概率
priority_queuepairdouble,int,vectorpairdouble,int,lesspairdouble,int heap; 最大堆 因为要概率最大
heap.push({1,begin});
while(heap.size())
{
int node=heap.top().second;
heap.pop();
if(vis[node])continue;
for(int i=h[node];~i;i=ne[i]){
int now_node=e[i];double W=w[i];
if(dis[now_node]dis[node]W) 如果可以更新
{
dis[now_node]=dis[node]W;
heap.push({dis[now_node],now_node});
}
}
vis[node]=true;
}
return dis[end];
}
};
一家快递公司希望在新城市建立新的服务中心。公司统计了该城市所有客户在二维地图上的坐标,并希望能够以此为依据为新的服务中心选址:使服务中心 到所有客户的欧几里得距离的总和最小 。
给你一个数组 positions ,其中 positions[i] = [xi, yi] 表示第 i 个客户在二维地图上的位置,返回到所有客户的 欧几里得距离的最小总和 。
换句话说,请你为服务中心选址,该位置的坐标 [xcentre, ycentre] 需要使下面的公式取到最小值:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bz47Nzx9-1594541358071)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads20200712q4_edited.jpg)]
与真实值误差在 10^-5 之内的答案将被视作正确答案。
示例 1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-00oCloz4-1594541358073)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads20200712q4_e1.jpg)]
输入:positions = [[0,1],[1,0],[1,2],[2,1]]
输出:4.00000
解释:如图所示,你可以选 [xcentre, ycentre] = [1, 1] 作为新中心的位置,这样一来到每个客户的距离就都是 1,所有距离之和为 4 ,这也是可以找到的最小值。
示例 2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7ZsuyP7-1594541358075)(httpsassets.leetcode-cn.comaliyun-lc-uploaduploads20200712q4_e3.jpg)]
输入:positions = [[1,1],[3,3]]
输出:2.82843
解释:欧几里得距离可能的最小总和为 sqrt(2) + sqrt(2) = 2.82843
示例 3
输入:positions = [[1,1]]
输出:0.00000
示例 4
输入:positions = [[1,1],[0,0],[2,0]]
输出:2.73205
解释:乍一看,你可能会将中心定在 [1, 0] 并期待能够得到最小总和,但是如果选址在 [1, 0] 距离总和为 3
如果将位置选在 [1.0, 0.5773502711] ,距离总和将会变为 2.73205
当心精度问题!
示例 5
输入:positions = [[0,1],[3,2],[4,5],[7,6],[8,9],[11,1],[2,12]]
输出:32.94036
解释:你可以用 [4.3460852395, 4.9813795505] 作为新中心的位置
提示
几何题 算是难的吧
毕竟不懂算法就推不出来
所以我也不分析怎么思考了 必须学过才会的
懂的就不会看我文章了 应该搜论文去了hh
这里介绍一种简单的算法 三分查找
这是因为欧氏距离有着这样的规律:
我们先看公式: ans=sum(sqrt( (x-xi)² + (y-yi)² ))
假如我们把x固定了 那么ans的最小值 就是有关y的一个二次函数的最小值
而二次函数的最小值我们是可以用三分法来找到最值的
那么同样道理 对于x 假如对应x的y都知道 那么对于每个xj而言yj是固定的 那么y可以写成关于x的函数getY(x) 那么这也是一个二次函数最值的问题 因此可以三分
所以总的就是三分套上三分
总的时间复杂度是 O(nlogmlogm) m为精度 此处精度大概为1e-8 n为50
当然 你二分个100~200次 怎么来说精度也够了
class Solution {
public
double getMinDistSum(vectorvectorint& p) {
int n=p.size();
auto getSum = [&n,&p](double x,double y){ 获取固定(x,y)到全部点的距离之和
double sum=0;
for(int i=0;in;i++)
sum+=sqrt((x-p[i][0])(x-p[i][0])+(y-p[i][1])(y-p[i][1]));
return sum;
};
auto getY = [&getSum](double x){ 获取固定x的y的最值
double l=0,r=100;
for(int i=0;i100;i++)
{
double m1=(l+r)2,m2=(m1+r)2;
if(getSum(x,m1)getSum(x,m2))r=m2;
else l=m1;
}
return getSum(x,l);
};
double l=0,r=100;
for(int i=0;i100;i++) 可以去找下x的最值是多少
{
double m1=(l+r)2,m2=(m1+r)2;
if(getY(m1)getY(m2))r=m2; 可以看到比较的是关于x的二次函数
else l=m1;
}
return getY(l);
}
};