当前位置:网站首页>co_fun 社区提供 微软秋招笔试 8.6 题解
co_fun 社区提供 微软秋招笔试 8.6 题解
2022-08-07 16:53:00 【GreyKa】
微软秋招笔试 8.6 题解
本文由 co_fun 内推社区 GreyKa 提供,欢迎加入社区qq群 618358435,三十几家大厂员工为你内推。
题目1
题意:
有一个长度为 1000000 的字符串,由 . 和 x 组成,每次你能选择字符串中的一个子串(要求子串中的所有字符都是 x),把他变成 . 。每次操作的开销为子串长度 +1。给定最大开销,问你最多能讲多少 x 变为 .。
解题思路:
可以很显然的发现,因为每次操作都会有额外一点开销,因此对尽可能长的串进行操作的浪费最小。因此我们可以把连续的 x 的串的长度统计出来,每次操作优先选取最大的,直到剩余的开销不足以对当前最大的段进行操作时,截取最大的段当中的一部分进行操作即可。
代码
#include<bitsdc++.h>
using namespace std;
priority_queue<int> pq;
int solution(string &S, int B) {
S=S+".";
int rec=0;
for(int i=0;i<S.size();i++){
if(S[i]=='x'){
rec++;
}else{
if(rec>0){
pq.push(rec);
rec=0;
}
}
}
int ans=0;
while((B>1)&&pq.size()){
int temp=pq.top();
pq.pop();
int now=min(B-1,temp);
ans+=now;
B-=(now+1);
}
return ans;
}
题目2
题意:
给你一个由 R 和 W 组成的长度为 1e6 的字符串,你每次操作可以选择其中两个位置相邻的字符进行交换,问你最少操作多少次,可以使得所有的 R 字符变成连续的一段。
解题思路
这题是很经典的一个中位数的题的变种。
我们可以猜测,所有的 R 字符中,会有一个是不用变化位置的,而其他所有的R会以它为最中间的位置靠拢。
证明如下:
首先我们先假设已经知道了变换后的 R 是原串中的某一段,我们可以找到一个位置,使得他两边的 R 都是原串的左边和右边移动过来的。这种情况下面,可以发现,若左边的元素数量小于右边,则我们把分割线移动到右边的第一个元素的左侧,能够获得更优解,如图中的绿色线。若分割线为红线,则右边的 3 个元素都会移动一次 x 的距离,对答案产生 3x 的贡献,若将绿色线作为分割线,则左边的 2 个元素都会再移动一次 x 的距离,产生 2x 的贡献,更优。反之亦然,而且当两边元素数量一样时,也能保证不会使得答案更差。
知道了这个结论以后,我们怎么确定哪个 R 是不动的,又如何计算值呢?如下图,假设第三个 R 是不动的那个,则我们观察左右两边的 R 在向中间靠拢的时候,第二个 R 所走的那段距离会被走两次(他自己走一次,他左边的 R 也会走一次)。因此我们发现,最外侧的第 1 个 R 到第 2 个 R 的距离会被走 1 次,而第 2 个 R 到第 3 个 R 的距离会被走 2 次,第 n 个 R 到第 n+1 个 R 的距离会被走 n 次。因此总答案的计算如图,从外围到中心,第 i 个间距的值乘以 i,再全部相加,就是结果。因此这题就变成了给间距去从外层到里层分配系数。明显可以知道,分割线左右两边的间距数量越接近答案越优。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int solution(string& S)
{
ll ans=0;
int last=-1;
vector<int> v;
for(int i=0;i<S.size();i++)
{
if(S[i]=='R')
{
if(last!=-1)
v.push_back(i-last-1);
last=i;
}
}
for(int i=0;i<v.size()/2;i++)
ans+=(i+1)*v[i];
for(int i=0; i<(v.size()+1)/2;i++)
ans+=(i+1)*v[v.size()-i-1];
// 题目要求答案大于1e9输出-1
if(ans>1000000000)
return -1;
return ans;
}
题目3
有 n 个病人和 m 个医生,每个病人有两个期望医生,每个医生只能接待一个病人。问有没有一种安排方法,能让每个病人都看上自己期望的医生。(n,m为 100000 和 200000)
解题思路
很明显的二分图匹配问题,因此这题如果不会做可以直接套二分图匹配算法 匈牙利算法 板子,复杂度不够但是能骗到不少分。如果学过网络流,用 Dinic 算法应该也能通过本题。不过这都不是企业招聘笔试算法考纲内的东西。下面我们来说正解。(感谢 uniecho1 学弟的启发)
我们先将病人和期望的两个医生连接,变成一个二分图。我们考虑一个联通的二分图(很显然如果原图上有多个连通块,不同连通块之间互相不可能产生影响。两个连通块之间医生和病人之间没有任何关系,匹配不会互相影响。),若图中所有的连通块都能满足匹配需求,则能满足题目的匹配要求,反之有一个连通块不能满足要求,则直接匹配失败。
对于一个联通图,我们可以知道如果当中医生的数量如果少于病人,则会直接匹配失败。
那么我们只需要考虑医生数量大于等于病人的情况。首先如果医生数量大于病人数量,我们会发现,医生数量必然是病人数量 +1,只有这样才能保证这个图联通(如果把病人当作连接两个医生的一条边,会发现这张图其实就是一棵树)。此时就很明显,所有的病人都能匹配上。
当医生和病人数量相同的时时候,分为两种情况:
第一种情况是,所有的医生都有两个相关病人。这时候发现原图会形成一个环(二分图上,每个点都有两个度,说明每个点都可以被进入和走出一次,最终走完整张图),此时显然能够完全匹配上。
第二种情况是,存在医生关联大于或者小于 2 个病人。因为医生的数量大于等于病人,而每个病人会提供 2 条边,若存在医生拥有超过 2 个相关病人,则必然会有医生只有一个相关病人(不然总边数会大于 2n)。很显然这个只有一个相关病人的医生直接和那个病人贪心匹配是最优的。这时候我们会发现有另外一个医生的连边会减少 1,但是不会导致这个医生的连线变成 0 (否则这三个点会变成单独一个连通块,和我们题设不符)。因此每次贪心操作会导致一个医生和一个病人的减少。有没有发现,出现了递归的子问题?
因此在医生和病人数量相同的情况下,只有两种情况:第一种情况下,直接匹配完成。第二种情况下,必然可以贪心拿走一对病人和医生,依然是最初病人和医生相同的状态。因此根据归纳法,我们可以知道病人和医生数量相同时,必然能够完全匹配。
综上所述,问题变成了对于每个二分图连通块,判断其中医生数量是否大于等于病人,如果是则这个连通块匹配成功,反之失败。我们只需要一遍搜索,对每个连通块计算病人和医生数量即可。
代码
#include<iostream>
#include<vector>
#define MAXN 400000
using namespace std;
vector<int> e[MAXN];
bool vis[MAXN];
void dfs(int now,int& p,int &d,const int& N)
{
if(vis[now])return;
vis[now]=true;
if(now<=N)p++;
else d++;
for(int i=0;i<e[now].size();i++)
dfs(e[now][i], p, d, N);
}
bool check(int now,int N)
{
int p=0,d=0;
dfs(now,p,d,N);
if(p<=d)return true;
return false;
}
int solution(int A[], int B[], int N, int S)
{
for(int i=0;i<N;i++)
{
e[i+1].push_back(A[i]+N);
e[A[i]+N].push_back(i+1);
e[i+1].push_back(B[i]+N);
e[B[i]+N].push_back(i+1);
}
for(int i=1;i<=N;i++)
if(!check(i,N))
return 0;
return 1;
}
边栏推荐
- 服务主机:本地服务网络受限怎么办_服务主机本地系统网络受限的解决方法
- 电脑上怎么打符号 电脑上怎么输入特殊符号
- 如何解决win7中蓝屏代码0x0000007b-
- 嵌入式系统驱动高级【1】——设备模型
- 运行关机命令是什么 电脑运行自动关机的指令是什么
- 戴尔灵越15pro配置 戴尔灵越15pro值得买吗
- 嵌入式系统驱动初级【10】——中断处理下_下半部机制
- 云/移动端媒体处理技术分享
- Outlook 2016 set the mail format for plain text
- Chrome scroll bar style modification how to operate Chrome browser scroll bar style customization method
猜你喜欢

Does the laptop have bluetooth? How to turn on bluetooth on the laptop

网页不让复制的文字如何复制 不允许复制的网页怎么复制

win7怎么调保护眼睛的电脑设置_win7保护眼睛的颜色设置方法

w7电脑格式化怎么弄 笔记本电脑如何格式化win7

如何解决win7系统时间不准

What to do if the computer can't delete the folder

电脑怎样安装读卡器驱动 电脑无法识别读卡器驱动安装步骤

Why are test/dev programmers paid so much?

轻松解决笔记本触摸板失灵有妙招

电脑系统是win7好还是win8好_电脑系统w7和w8哪个好
随机推荐
excel打印区域怎么调整 excel 打印区域重新设置
怎么能保护眼睛 电脑什么颜色保护眼睛
电脑删不掉文件夹怎么办 电脑文件夹老是删不掉解决方法
如何解决win7中蓝屏代码0x0000007b-
Unity Webgl发布的一些注意的点
win7怎么升级成sp1_win7怎么更新到sp1
R语言向前或者向后移动时间序列数据(自定义滞后或者超前的期数):使用lag函数将时间序列数据向后移动一天(设置参数k为负值)
Technical analysis of development of digital currency spot contract exchange system
鼠标单击偶尔变双击了怎么办_电脑鼠标单击变双击了怎么设置
【kali-权限提升】(4.1)假冒令牌攻击、本地提权:流程
Chrome scroll bar style modification how to operate Chrome browser scroll bar style customization method
win7安全模式进不去怎么办 win7无法进入安全模式如何解决
常见的海量数据面试题总结
Win7系统下打开软件提示缺少sqlite3.dll文件如何解决
Citrix Virtual Apps和Desktops 2206更新概览
短视频自嗨无法流量变现大刚运维代运营
Analysis of various related architectures of MCU
Redis high frequency interview questions full version
What to do if the computer can't delete the folder
利用联合索引优化filesoert