[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

posted @ 2020-08-26 21:35  Jamest  阅读(162)  评论(0编辑  收藏  举报