双周赛:
第一题:找到最接近0的数字
原题链接
示例:
思路:找绝对值最小或绝对值相等是本身较大的数 。
class Solution {
public:
int findClosestNumber(vector<int>& nums) {
int res=nums[0];
for(auto x:nums){
if(abs(res)>abs(x)||abs(res)==abs(x)&&res<x){
res=x;
}
}
return res;
}
};
第二题: 买钢笔和铅笔的方案数
原题链接
示例:
思路:直接枚举,固定其中某种笔的数量,用剩余金额算能买另一种笔的数量。
class Solution {
public:
long long waysToBuyPensPencils(int total, int cost1, int cost2) {
long long res=0;
for(int i=0;i<=total/cost1;i++){
res+=(total-i*cost1)/cost2+1;//买0支笔的情况也要算
}
return res;
}
};
第三题:设计一个ATM机器
原题链接
示例:
思路:
- 存钱时,相应面值个数增加,使用long long
- 取钱时,先判断能否按要求取钱,再更新相应面值个数
class ATM {
public:
int money[5]={20,50,100,200,500};//面值
vector<long long> count;
ATM() {
count=vector<long long>(5);//记录各面值美元的数量
}
void deposit(vector<int> banknotesCount) {//存钱
for(int i=0;i<banknotesCount.size();i++){
count[i]+=banknotesCount[i];
}
}
vector<int> withdraw(int amount) {//取钱
vector<int> res(5);//优先大面值
for(int i=4;i>=0;i--){
res[i]=min(count[i],(long long)amount/money[i]);
amount-=res[i]*money[i];
}
if(amount>0){//还有剩余则拒绝请求
return {-1};
}
for(int i=0;i<5;i++){
count[i]-=res[i];
}
return res;
}
};
第四题:节点序列的最大得分
原题链接
示例:
思路:
- 题目要找相邻节点有边相连且长度为4的合法节点序列的最大分数
- a-x-y-b 若a,x,y,b是这样的一个序列 为找最大分数则枚举中间边即x-y
- 把与x相邻的点中,分数最大且不同于y和b的点作为a
- 把与y相邻的点中,分数最大且不同于a和x的点作为b
- 则最优a一定在与x相邻的最大三个点中
如图:
当枚举到边[1,2]时,黄色圈是与1相邻的前三大点,绿色圈是与2相邻的前三大点
重合部分即为寻找的最大得分序列上的点
class Solution {
public:
int maximumScore(vector<int>& scores, vector<vector<int>>& edges) {
int res=-1,n=scores.size();
vector<vector<int>> g(n);
for(auto &e:edges){//建无向图
g[e[0]].push_back(e[1]);
g[e[1]].push_back(e[0]);
}
for(int i=0;i<n;++i){
sort(g[i].begin(),g[i].end(),[&](int a,int b){
return scores[a]>scores[b];
});//把与i相邻的点按从大到小排列
}
for(auto &e:edges){//枚举边
int u=e[0],v=e[1];
for(int i=0;i<min(3,(int)g[u].size());i++){//与u相邻的前三大点
for(int j=0;j<min(3,(int)g[v].size());j++){//与v相邻的前三大点
if(g[u][i]!=v&&g[v][j]!=u&&g[u][i]!=g[v][j])//在a-u-v-b中,a!=v b!=u a!=b
res=max(res,scores[u]+scores[v]+scores[g[u][i]]+scores[g[v][j]]);
}
}
}
return res;
}
};