力扣第203场周赛 Apare_xzc

力扣第203场周赛


比赛链接:第203场周赛 - 力扣


1560. 圆形赛道上经过次数最多的扇区

在这里插入图片描述
模拟计数即可

class Solution {
public:
    vector<int> mostVisited(int n, vector<int>& rounds) {
        vector<int> cnt(n+1);
        vector<int>v;
        int m = rounds.size();
        if(!m) return v;
        cnt[rounds[0]]=1;
        for(int i=1;i<m;++i) {
            int k = rounds[i-1];
            do {
                if(++k==n+1) k=1;
                cnt[k]++;
            }while(k!=rounds[i]);
        }
        int ans = 1;
        for(int i=2;i<=n;++i) {
            if(cnt[i]>cnt[ans]) ans = i;
        }
        for(int i=1;i<=n;++i) {
            if(cnt[i]==cnt[ans]) v.push_back(i);
        }
        return v;
    }
};

1561. 你可以获得的最大硬币数目

有 3n 堆数目不一的硬币,你和你的朋友们打算按以下方式分硬币:

每一轮中,你将会选出 任意 3 堆硬币(不一定连续)。
Alice 将会取走硬币数量最多的那一堆。
你将会取走硬币数量第二多的那一堆。
Bob 将会取走最后一堆。
重复这个过程,直到没有更多硬币。
给你一个整数数组 piles ,其中 piles[i] 是第 i 堆中硬币的数目。

返回你可以获得的最大硬币数目。

在这里插入图片描述
每次让Bob取最小的,Alice取第二大的,取n/3次。贪心。排序之后依次选a[n-2],a[n-4]… 选n/3个

class Solution {
public:
    int maxCoins(vector<int>& piles) {
        int n = piles.size();
        if(!n) return 0;
        int ans = 0;
        sort(piles.begin(),piles.end());
        int id = n-2;
        int t = n/3;
        for(int i=1;i<=t;++i) {
            ans += piles[id];
            id -= 2;
        }
        return ans;
    }
};

1562. 查找大小为 M 的最新分组

给你一个数组 arr ,该数组表示一个从 1 到 n 的数字排列。有一个长度为 n 的二进制字符串,该字符串上的所有位最初都设置为 0 。

在从 1 到 n 的每个步骤 i 中(假设二进制字符串和 arr 都是从 1 开始索引的情况下),二进制字符串上位于位置 arr[i] 的位将会设为 1 。

给你一个整数 m ,请你找出二进制字符串上存在长度为 m 的一组 1 的最后步骤。一组 1 是一个连续的、由 1 组成的子串,且左右两边不再有可以延伸的 1 。

返回存在长度 恰好 为 m 的 一组 1 的最后步骤。如果不存在这样的步骤,请返回 -1 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-latest-group-of-size-m
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
在这里插入图片描述

  • 用L[x]表示位置x最左边连续的1的位置,用R[x]表示位置x最右边连续的1的位置。开始初始化都为-1
  • 插入一个结点后,先修改L[x] = R[x] = x,然后看是否可以和左边合并,如果可以,更新L[x]=L[x-1], 看是否可以和右边合并,如果可以,更新R[x] = R[x+1], 然后我们更新左边连通块的值和右边连通块的值。如果左边有1,那么我们让R[L[x-1]] = R[x-1] = R[x], 如果右边也有1,那么让L[x+1] = L[R[x+1]] = L[x]
  • 我们只需要更新连通块左右端点的L[i]和R[i]即可,中间的可以不管。因为我们在进行区间合并的时候,只要知道区间端点就可以知道是否要合并。
  • 我们可以维护一个cnt,表示当前长度为m的连续1的个数。用last记录最后的出现m的轮数。在插入的时候,插入a[x]=1, 我们计算出R[x]和L[x]之后,如果R[x]-L[x]+1==m,那么说明新增一个,cnt++, 如果左边a[x-1]所在连通块本来长度为m,加入a[x]后边长,那么cnt–, 右边同理。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
    int findLatestStep(vector<int>& arr, int m) {
        int n = arr.size();
        vector<int> v(n+1,0),L(n+1,-1),R(n+1,-1);
        int cnt = 0; //长度为m的最长子串的个数
        int last = -1;
        for(int i=0;i<n;++i) {
            int x = arr[i];
            v[x] = 1;
            L[x] = R[x] = x;
            if(x!=1&&v[x-1]==1) {
                L[x] = L[x-1];
            }
            if(x!=n&&v[x+1]==1) {
                R[x] = R[x+1];
            }
            if(R[x]-L[x]+1==m) {
                ++cnt;
            }
            if(x!=1&&v[x-1]==1) {
                if(R[x-1]-L[x-1]+1==m) --cnt;
                R[x-1] = R[x];
                R[L[x-1]] = R[x];
            }
            if(x!=n&&v[x+1]==1) {
                if(R[x+1]-L[x+1]+1==m) --cnt;
                L[x+1] = L[x];
                L[R[x+1]] = L[x];
            }
            if(cnt>0) last = i+1;
        }
        return last;
    }
};
int main(void) {
	Solution * sol = new Solution();
	vector<int> v = {3,2,5,6,10,8,9,4,1,7}; 
	cout<<sol->findLatestStep(v,3)<<endl;
	return 0;
} 

1563. 石子游戏 V

几块石子 排成一行 ,每块石子都有一个关联值,关联值为整数,由数组 stoneValue 给出。

游戏中的每一轮:Alice 会将这行石子分成两个 非空行(即,左侧行和右侧行);Bob 负责计算每一行的值,即此行中所有石子的值的总和。Bob 会丢弃值最大的行,Alice 的得分为剩下那行的值(每轮累加)。如果两行的值相等,Bob 让 Alice 决定丢弃哪一行。下一轮从剩下的那一行开始。

只 剩下一块石子 时,游戏结束。Alice 的分数最初为 0 。

返回 Alice 能够获得的最大分数 。

在这里插入图片描述
开始想的是贪心,每次二分出左边stoneValue的和不超过一半的最长序列,向下递归,二分出右边stoneValue的和不超过一般的最长序列,向下递归。后来发现,这样贪心可能有问题[98,77,24,49,6,12,2,44,51,96]这个数据输出应该是330,贪心的输出是307。 所以发现还得遍历每一个不超过一半的序列,都递归。但是这样O(n^3)会超时,所以加一个记忆化即可。

贪心二分+递归代码如下

class Solution {
public: 
    void dfs(int st,int ed,int presum,int& ans,vector<int>& s,vector<pair<int,int> >&r) {
        if(ed<=st) {
              ans = max(ans,presum);
//            for(auto x:r) printf("[%d,%d],",x.first,x.second);
//            cout<<" presum = "<<presum<<endl;
            return;
        }
        int sum = s[ed]-s[st-1];
        int left = st-1, right = ed+1;
        while(right-left>1) {
            int mid = (left+right)>>1;
            if((s[mid]-s[st-1])*2<=sum) left = mid;
            else right = mid;
        }
        r.push_back(make_pair(st,left));
        dfs(st,left,presum+s[left]-s[st-1],ans,s,r);
        r.pop_back();
        left = st-1,right = ed+1;
        while(right-left>1) {
            int mid = (right+left)>>1;
            if((s[ed]-s[mid-1])*2<=sum) right = mid;
            else left = mid;
        }
        r.push_back(make_pair(right,ed));
        dfs(right,ed,presum+s[ed]-s[right-1],ans,s,r);
        r.pop_back();
    }
    int stoneGameV(vector<int>& stoneValue) {
        int n = stoneValue.size();
        if(!n) return 0;
        vector<int> s(n+1,0);
        for(int i=1;i<=n;++i)
            s[i] = s[i-1]+stoneValue[i-1];
        int ans = 0;
        vector<pair<int,int>> r;
        dfs(1,n,0,ans,s,r);
        return ans;
    }
};

记忆化搜索代码如下:

#include <bits/stdc++.h>
using namespace std; 
class Solution {
public: 
	int dfs(int st,int ed,vector<int>& s,vector<vector<int>>& dp) {
		if(dp[st][ed]!=-1) return dp[st][ed];
		if(st>=ed) {
			return dp[st][ed] = 0;
		}
		int & ans = dp[st][ed] = 0;
		for(int mid=st;mid<ed;++mid) {
			int sumL = s[mid]-s[st-1], sumR = s[ed]-s[mid];
			if(sumL<=sumR) ans = max(ans,sumL+dfs(st,mid,s,dp));
			if(sumL>=sumR) ans = max(ans,sumR+dfs(mid+1,ed,s,dp));
		}
		return ans;
	}
    int stoneGameV(vector<int>& stoneValue) {
        int n = stoneValue.size();
        if(!n) return 0;
        vector<int> s(n+1,0);
        vector<vector<int> > dp(n+1,vector<int>(n+1,-1));
        for(int i=1;i<=n;++i)
            s[i] = s[i-1]+stoneValue[i-1];
		return dfs(1,n,s,dp);
    }
};
int main(void) {
	Solution * sol = new Solution();
	vector<int> v = {98,77,24,49,6,12,2,44,51,96};
	cout<<sol-> stoneGameV(v)<<endl;
	
	return 0;
}

2020.9.4
13:31


猜你喜欢

转载自blog.csdn.net/qq_40531479/article/details/108402149