LeetCode双周赛11
LeetCode双周赛11
5088.等差数列中缺失的数字
有一个数组,其中的值符合等差数列的数值规律,也就是说:
在 0 <= i < arr.length - 1 的前提下,arr[i+1] - arr[i] 的值都相等。
我们会从该数组中删除一个 既不是第一个 也 不是最后一个的值,得到一个新的数组 arr。
给你这个缺值的数组 arr,请你帮忙找出被删除的那个数。
示例 1:
输入:arr = [5,7,11,13]
输出:9
解释:原来的数组是 [5,7,9,11,13]。示例 2:
输入:arr = [15,13,12]
输出:14
解释:原来的数组是 [15,14,13,12]。提示:
3 <= arr.length <= 1000
0 <= arr[i] <= 10^5
因为是符合等差数列所以如果中间被删去了一个数,那么被删去数两边的差的绝对值(可能是负数)必定比正常两个数间的差的绝对值要大,所以可以记第1和第2间的差再依次比较直到不相等。再比较绝对值大小,就可以得出谁是正常差。
class Solution {
public:
int missingNumber(vector<int>& arr)
{
int n=arr.size();
int idx1;
int idx2;
int pos;
idx1=arr[1]-arr[0];
for(int i=1;i<n-1;i++)
{
idx2=arr[i+1]-arr[i];
if(idx1!=idx2)
{
pos=i;
break;
}
}
if(abs(idx1)>abs(idx2))
{
return arr[0]+idx2;
}
else
{
return arr[pos]+idx1;
}
}
};
5089.安排会议日程
你是一名行政助理,手里有两位客户的空闲时间表:slots1 和 slots2,以及会议的预计持续时间 duration,请你为他们安排合适的会议时间。
「会议时间」是两位客户都有空参加,并且持续时间能够满足预计时间 duration 的 最早的时间间隔。
如果没有满足要求的会议时间,就请返回一个 空数组。
「空闲时间」的格式是 [start, end],由开始时间 start 和结束时间 end 组成,表示从 start 开始,到 end 结束。
题目保证数据有效:同一个人的空闲时间不会出现交叠的情况,也就是说,对于同一个人的两个空闲时间 [start1, end1] 和 [start2, end2],要么 start1 > end2,要么 start2 > end1。
示例 1:
输入:slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration = 8
输出:[60,68]示例 2:
输入:slots1 = [[10,50],[60,120],[140,210]], slots2 = [[0,15],[60,70]], duration = 12
输出:[]
提示:
1 <= slots1.length, slots2.length <= 10^4
slots1[i].length, slots2[i].length == 2
slots1[i][0] < slots1[i][1]
slots2[i][0] < slots2[i][1]
0 <= slots1[i][j], slots2[i][j] <= 10^9
1 <= duration <= 10^6
比赛的时候写了个贼复杂的滑动窗口,结果wa了n次都没调出来。。。
其实有更简单的做法,先将这两个序列排序(题目很坑,这两序列不一定是有序的),因为最后结果的区间开头必定是一个现成的,那么就可以边枚举每个阶段的开头,边用一个指针指向另一个序列。每次检查是否相交,如果相交区间是否足够大,如果相交但不够大则将指针后移,如果不相交则枚举下一个区间。
另一个更好写的方法,用双指针,从开始记录两个区间的左最大和右最小(两者相减就是重叠部分),如果某区间的右端最小那么就应该将指针移向下一个(贪心的思想)。
bool cmp(vector<int> a,vector<int> b)
{
return a[0]<=b[0];
}
class Solution {
public:
vector<int> minAvailableDuration(vector<vector<int>>& slots1, vector<vector<int>>& slots2, int duration)
{
int n1=slots1.size();
int n2=slots2.size();
sort(slots1.begin(),slots1.end(),cmp);
sort(slots2.begin(),slots2.end(),cmp);
int st;
int pt1=0;
int pt2=0;
int left;
int right;
bool getans=0;
while(pt1<n1 && pt2<n2)
{
right=max(slots1[pt1][0],slots2[pt2][0]);
left=min(slots1[pt1][1],slots2[pt2][1]);
if(left-right>=duration)
{
getans=1;
st=right;
break;
}
if(left==slots1[pt1][1])
{
pt1++;
}
else
{
pt2++;
}
}
vector<int> ans;
ans.clear();
if(getans)
{
ans.push_back(st);
ans.push_back(st+duration);
}
return ans;
}
};
5090.抛掷硬币
有一些不规则的硬币。在这些硬币中,prob[i] 表示第 i 枚硬币正面朝上的概率。
请对每一枚硬币抛掷 一次,然后返回正面朝上的硬币数等于 target 的概率。
示例 1:
输入:prob = [0.4], target = 1
输出:0.40000示例 2:
输入:prob = [0.5,0.5,0.5,0.5,0.5], target = 0
输出:0.03125提示:
1 <= prob.length <= 1000
0 <= prob[i] <= 1
0 <= target <= prob.length
如果答案与标准答案的误差在 10^-5 内,则被视为正确答案。
显而易见的概率dp,定义f(i,j)是抛了前i个硬币有j个朝上的概率。
再次显而易见f(i,j)=f(i-1,j-1)*i项朝上的概率+f(i-1,j)*i项朝下的概率
当然本题可以用滚动数组优化,不过数据量很小leetcode内存又能开很大。。。
double f[1005][1005];
class Solution {
public:
double probabilityOfHeads(vector<double>& prob, int target)
{
memset(f,0,sizeof(f));
int n=prob.size();
f[0][0]=1.00;
for(int i=1;i<=n;i++)
{
f[i][0]=f[i-1][0]*(1-prob[i-1]);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]+=f[i-1][j-1]*prob[i-1];
f[i][j]+=f[i-1][j]*(1-prob[i-1]);
}
}
return f[n][target];
}
};
5111.分享巧克力
你有一大块巧克力,它由一些甜度不完全相同的小块组成。我们用数组 sweetness 来表示每一小块的甜度。
你打算和 K 名朋友一起分享这块巧克力,所以你需要将切割 K 次才能得到 K+1 块,每一块都由一些 连续 的小块组成。
为了表现出你的慷慨,你将会吃掉 总甜度最小 的一块,并将其余几块分给你的朋友们。
请找出一个最佳的切割策略,使得你所分得的巧克力 总甜度最大,并返回这个 最大总甜度。
示例 1:
输入:sweetness = [1,2,3,4,5,6,7,8,9], K = 5
输出:6
解释:你可以把巧克力分成 [1,2,3], [4,5], [6], [7], [8], [9]。示例 2:
输入:sweetness = [5,6,7,8,9,1,2,3,4], K = 8
输出:1
解释:只有一种办法可以把巧克力分成 9 块。示例 3:
输入:sweetness = [1,2,2,1,2,2,1,2,2], K = 2
输出:5
解释:你可以把巧克力分成 [1,2,2], [1,2,2], [1,2,2]。提示:
0 <= K < sweetness.length <= 10^4
1 <= sweetness[i] <= 10^5
一个不太容易想到的方法(大佬除外),按值二分。我们二分巧克力的最小甜度minx,然后检查以当前方法能否分出k+1块,具体怎么检查,就是贪心的划分我们先记一个sum记录一段的和,一但其超过minx就划一块巧克力,这样一直划下去看能不能达到k+1。
为什么这样划分是对的呢?因为我们是检查的最小甜度,超过最小甜度一点点(或者刚好一样)可以使后面的划分地更多,而多出来的就可以分给一个人。
bool check(int minx,vector<int>& sweetness,int k)
{
int n=sweetness.size();
int sum=0;
int cnt=0;
for(int i=0;i<n;i++)
{
sum+=sweetness[i];
if(sum>=minx)
{
cnt++;
sum=0;
if(cnt>=k)
{
return true;
}
}
}
return false;
}
class Solution {
public:
int maximizeSweetness(vector<int>& sweetness, int K)
{
K+=1;
int n=sweetness.size();
int r=1e9+7;
int l=0;
int mid;
int ans=0;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid,sweetness,K))
{
l=mid+1;
ans=max(ans,mid);
}
else
{
r=mid-1;
}
}
return ans;
}
};
这次比赛打得很惨烈。。。主要还是在t2上磨了太久,果然还是要锻炼码大程序的能力啊。