• 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上磨了太久,果然还是要锻炼码大程序的能力啊。

  • 相关阅读:
    【解决】client does not support authentication
    DesktopLayer.exe专杀
    SVN客户端操作(clean up|commit|update)系统找不到指定的文件
    怎样判断一个exe可执行程序(dll文件)是32位的还是64位的
    Windows 调用OpenProcess失败
    win10 请求操作需要提升解决方案
    LINUX下C++编程如何获得某进程的ID
    GitHub
    Git分支管理
    Gi命令行操作
  • 原文地址:https://www.cnblogs.com/Heizesi/p/11710003.html
Copyright © 2020-2023  润新知