• [Leetcode Weekly Contest]203


    链接:LeetCode

    [Leetcode]5495. 圆形赛道上经过次数最多的扇区

    给你一个整数 n 和一个整数数组 rounds 。有一条圆形赛道由 n 个扇区组成,扇区编号从 1 到 n 。现将在这条赛道上举办一场马拉松比赛,该马拉松全程由 m 个阶段组成。其中,第 i 个阶段将会从扇区(rounds[i - 1])开始,到扇区(rounds[i])结束。举例来说,第 1 阶段从(rounds[0])开始,到(rounds[1])结束。
    请你以数组形式返回经过次数最多的那几个扇区,按扇区编号 升序 排列。

    实际上只需要关注第一个和最后一个扇区即可。 中间不管有多少个值多少圈, 对于每个扇区增加的次数都是相同的。

    根据题意暴力即可。

    class Solution {
    public:
        vector<int> mostVisited(int n, vector<int>& rounds) {
            vector<int> res;
            int m=rounds.size();
            int start=rounds.front(),end=rounds.back();
            if(start<=end){
                for(int i=start;i<=end;++i){
                    res.push_back(i);
                }
            }
            else{
                for(int i=1;i<=end;++i){
                    res.push_back(i);
                }
                for(int i=start;i<=n;++i){
                    res.push_back(i);
                }
            }
            return res;
        }
    };
    

    [Leetcode]5496. 你可以获得的最大硬币数目

    有 3n 堆数目不一的硬币,你和你的朋友们打算按以下方式分硬币:
    每一轮中,你将会选出 任意 3 堆硬币(不一定连续)。

    • Alice 将会取走硬币数量最多的那一堆。
    • 你将会取走硬币数量第二多的那一堆。
    • Bob 将会取走最后一堆。

    重复这个过程,直到没有更多硬币。
    给你一个整数数组 piles ,其中 piles[i] 是第 i 堆中硬币的数目。
    返回你可以获得的最大硬币数目。

    以三个为一组,你会取走硬币数量第二多的那一堆,贪心思想,在每次选取后只需要让剩余堆中的最大值最小。

    class Solution {
    public:
        int maxCoins(vector<int>& piles) {
            sort(piles.begin(),piles.end(),[](int l, int r) -> bool {
                return l > r;});
            int res=0,n=piles.size();
            for(int i=0;i<n/3;++i){
                res += piles[2*i+1];
            }
            return res;
        }
    };
    

    [Leetcode]5497. 查找大小为 M 的最新分组

    给你一个数组 arr ,该数组表示一个从 1 到 n 的数字排列。有一个长度为 n 的二进制字符串,该字符串上的所有位最初都设置为 0 。
    在从 1 到 n 的每个步骤 i 中(假设二进制字符串和 arr 都是从 1 开始索引的情况下),二进制字符串上位于位置(arr[i])的位将会设为 1 。
    给你一个整数 m ,请你找出二进制字符串上存在长度为 m 的一组 1 的最后步骤。一组 1 是一个连续的、由 1 组成的子串,且左右两边不再有可以延伸的 1 。
    返回存在长度 恰好 为 m 的 一组 1  的最后步骤。如果不存在这样的步骤,请返回 -1 。

    设置两个哈希表,一个um代表每个位置上的1的长度,一个freq代表出现m的一组1的次数。在每次更新时,我们即可更新freq即可,为了消去由于合并可能会小时的一组1,我们在每次更新的时候,只需要更新连续1的最左端和最右端即可。

    class Solution {
    public:
        int findLatestStep(vector<int>& arr, int m) {
            int n=arr.size(),res=-1;
            unordered_map<int,int> um;
            unordered_map<int,int> freq;
            for(int i=0;i<n;++i){
                int cur=1,num=arr[i];
                if(um.find(num-1)!=um.end()){
                    cur += um[num-1];
                    freq[um[num-1]] -= 1;
                }
                if(um.find(num+1)!=um.end()){
                    cur += um[num+1];
                    freq[um[num+1]] -= 1;
                }
                int left = um.find(num-1)!=um.end()?num-um[num-1]:num;
                int right = um.find(num+1)!=um.end()?num+um[num+1]:num;
                um[left] = cur;
                um[right] = cur;
    
                if(freq.find(cur)!=freq.end()){
                    freq[cur] ++;}
                else{
                    freq[cur] = 1;
                    }
                if((freq.find(m) != freq.end()&&(freq[m]>0))){
                    res = i+1;
                }
            }
            return res;
        }
    };
    

    [Leetcode]1563. 石子游戏 V

    几块石子 排成一行 ,每块石子都有一个关联值,关联值为整数,由数组 stoneValue 给出。
    游戏中的每一轮:Alice 会将这行石子分成两个 非空行(即,左侧行和右侧行);Bob 负责计算每一行的值,即此行中所有石子的值的总和。Bob 会丢弃值最大的行,Alice 的得分为剩下那行的值(每轮累加)。如果两行的值相等,Bob 让 Alice 决定丢弃哪一行。下一轮从剩下的那一行开始。
    只 剩下一块石子 时,游戏结束。Alice 的分数最初为 0 。
    返回 Alice 能够获得的最大分数 。

    动态规划,比较容易能想到(O(N^3))的做法。难点在于怎么实现(O(N^2))的时间复杂度。在每一次DP的过程中,由于要比较取不同分割点时的最大值,额外消耗了O(N)的时间复杂度,正确的做法是通过考虑使用前缀和数组来优化时间,即,通过mx1,mx2两个数组存储每一次遍历过程中左端和右端的较大值,通过额外空间优化时间复杂度。

    class Solution {
    public:
        int stoneGameV(vector<int>& st) {
            int n = st.size(), sums[n + 1];
            sums[0] = 0;
            for(int i = 0; i < n; ++i)
                sums[i + 1] = sums[i] + st[i];
    
            int dp[n][n], mx1[n][n], mx2[n][n];
            memset(dp, 0, sizeof(dp));
            for(int i = 0; i < n; ++i)
                mx1[i][i] = st[i], mx2[i][i] = st[i];
    
            for(int sp = 2; sp <= n; ++sp) {
                int m=0;
                for(int i = 0, j = i + sp - 1; j < n; ++i, ++j) {
                    while(sums[m + 1] - sums[i] < sums[j + 1] - sums[m + 1])
                        ++m;
                    if(m > i)
                        dp[i][j] = max(dp[i][j], mx1[i][m-1]);
                    if(m < j)
                        dp[i][j] = max(dp[i][j], mx2[m+1][j]);
                    if(sums[m + 1] - sums[i] == sums[j + 1] - sums[m + 1]) {
                        dp[i][j] = max(dp[i][j], mx1[i][m]);
                    }
                    mx1[i][j] = max(mx1[i][j-1], dp[i][j] + sums[j+1] - sums[i]);
                    mx2[i][j] = max(mx2[i+1][j], dp[i][j] + sums[j+1] - sums[i]);
                }
            }
            return dp[0][n-1];
        }
    };
    

    Leetcode

  • 相关阅读:
    c#中使用多线程访问winform中控件的若干问题(转)
    Winform 分页控件(转)
    C#争论:什么时候应该使用var?
    C#的Contains() 值还是引用
    DataTemplate
    DX11_基于GPU_ComputeShader的3D精确拾取
    串行的BitonicSort双调排序
    Directx11_使用Effect框架包装ComputeShader
    Silverlight自适应布局
    poj3626广搜
  • 原文地址:https://www.cnblogs.com/hellojamest/p/13568058.html
Copyright © 2020-2023  润新知