您好,欢迎来到化拓教育网。
搜索
您的当前位置:首页力扣第301场周赛+第82场双周赛+AcWing第59场周赛补题

力扣第301场周赛+第82场双周赛+AcWing第59场周赛补题

来源:化拓教育网

力扣第301场周赛

一.装满杯子需要的最短总时长

1.原题链接:

2.解题思路:

先将冷水、温水、热水的杯子数量从小到大排序,目标是匹配尽量多不同的饮料。

若amount[0] + amount[1] <= amount[2], 则答案就是amount[2];

若amount[0] + amount[1] > amount[2],考虑超出的部分t = amount[0] + amount[1] - amount[2]

        若t为偶数,我们可以先把amount[0]和amount[1]互相匹配t/2次进行“内部消化”,操作过后有amount[0] + amount[1] = amount[2],此时用一个amount[2]和一个amount[0]或amount[1]匹配即可,则答案为t / 2 + amount[2];

        若t为奇数,我们可以先把amount[0]和amount[1]互相匹配(t - 1) / 2次进行“内部消化”,操作过后有amount[0] + amount[1] - 1= amount[2],此时每次用一个amount[2]和一个amount[0]或amount[1]匹配,剩下一杯无法匹配,则答案为(t -1)/ 2 + amount[2] + 1;

综上当t为偶数或奇数得到的结果表达式,可以合并为(t + 1)/ 2 + amount[2];

3.参考代码:

class Solution {
public:
    int fillCups(vector<int>& amount) {
        sort(amount.begin(), amount.end());
        if(amount[0] + amount[1] <= amount[2])return amount[2];
        else
        {
            int t = amount[0] + amount[1] - amount[2];
            return (t + 1) / 2 + amount[2];
        }
    }
};

二.无限集中的最小数字

1.原题链接:

2.解题思路:

1.使用set存储已经删除的元素;

2.popSmallest:i从1开始判断,如果i不在set 中,就返回 i;

3.addBack:从st中删除num即可;

3.参考代码:

class SmallestInfiniteSet {
public:
    unordered_set<int> st;
    SmallestInfiniteSet() {
    }
    
    int popSmallest() {
        for (int i = 1; ; i++) {
            if (st.count(i) == 0) {
                st.insert(i);
                return i;
            }
        }
        return 0;
    }
    
    void addBack(int num) {
        st.erase(num);
    }
};

三.移动片段得到字符串

1.原题链接:

2.解题思路:

1.去掉'-'后的剩余字符应该是相同的,若不同直接返回false ;

2.然后用双指针遍历start[i]和target[j]

        若当前start[i]为L并且 i < j,由于L无法向右移动,则返回false;

        若当前start[i]为R并且 i > j,由于R无法向左移动,则返回false;

3.参考代码:

class Solution {
public:
    bool canChange(string start, string target) {
        int i , j = 0;
        int n = start.size();
        string s1, s2;
        for(int i = 0; i < n; i++)
        {
            if(start[i] != '_')s1 += start[i];
        }
        for(int j = 0; j < n; j++)
        {
            if(target[j] != '_') s2 += target[j];
        }
        if(s1 != s2) return false;

        for( int i = 0; i < n; i++){
            if(start[i] == '_') continue;
            while(target[j] == '_')j++;
            if(start[i] == 'R' && i > j || start[i] == 'L' && i < j)return false;
            j++;
        }
        return true;
    }
};

力扣第82场双周赛

一.计算布尔二叉树的值

1.原题链接:

2.解题思路:

1.如果当前节点没有孩子,说明是叶子节点,返回自己的值即可;

2.如果有孩子,递归调用evaluateTree函数获得左右孩子的布尔值,然后根据自身的val值,来决定对这两个布尔值进行或运算还是与运算。返回运算的结果即可。

3.参考代码:

class Solution {
public:
    bool evaluateTree(TreeNode* root) {
        if(root -> left){
            bool l = evaluateTree(root -> left);
            bool r = evaluateTree(root -> right);
            if(root -> val == 2)return l | r;
            else return l & r;
        }
        else{
            return root -> val;
        }
    }
};

二.坐上公交的最晚时间

1.原题链接:

2.解题思路:

遍历每辆公交车,处理可以上车的乘客;
如果要上车,需要在当前乘客前面时刻上车,更新上车时间;
如果可以在最后发车时间上车,更新为发车时刻;
遍历每辆公交车,更新最大出发时刻;

3.参考代码:

class Solution {
public:
    int latestTimeCatchTheBus(vector<int>& buses, vector<int>& passengers, int capacity) {
        set<int> st;
        for (auto &p :passengers) {
            st.insert(p);
        }
        sort(buses.begin(), buses.end());
        auto it = st.begin();
        int ans = 0;
        for (auto &bus : buses) {
            int cnt = 0;
            while (cnt++ < capacity && it != st.end() && *it <= bus) {
                /* 更新为当前可上车乘客的时间-1 */
                if (it == st.begin() || *prev(it) != *it - 1) { 
                    ans = *it - 1;
                }
                it++;
            }
            /* 更新为发车时刻 */
            if (cnt <= capacity && st.count(bus) == 0) {
                ans = bus;
            }
        }
        return ans;
    }
};

AcWing第59场周赛

一.数组操作

1.原题链接:

2.解题思路:

1.累加数组a[N]的所有元素,得到元素和s;

2.用b[N]记录a[N]的前缀和,并从小到大排序,则b[0]即为a[N]的最小前缀和

特别注意:按题目要求,当a[N]的所有元素均大于0时,则a[N]的最小前缀和为0

3.参考代码:

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 110;
int a[N],b[N],n,s = 0;

int main()
{
    cin >> n;
    for(int i = 0; i < N; i++)
    { cin >> a[i],s += a[i];}
    //求数组a[N]的前缀和,并存储于数组b[N]中
    for(int i = 0; i < N; i++)
   {
       if(i == 0)b[i] = a[i];
       else{
           b[i] = b[i - 1] + a[i];
       }
   }
   
   for(int i = 0 ; i < N;i ++)
   {if(a[i] > 0)b[i] = 0;
       else   sort(b, b + N);
   }
   
   cout << s - b[0] << endl;
   return 0;
}

二.减法操作

1.原题链接:

2.解题思路:

1.若n为偶数,则减的次数为 n/2,因为n的最小质因数为2  做差之后每次循环其最小质因数都为2
2.若n为奇数,则减的次数为 (n-n的最小质因数) / 2+1 ,因为n-n的最小质因数一定为偶数

3.参考代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

long long find(long long n){
    for(long long i=3;i<=n/i;i++){
        if(n%i==0){
            return i;
        }
    }
    return n;
}
int main(){
     long long n;
     scanf("%lld",&n);
     long long cnt;
     if(n%2==0) cnt=n/2;
     else cnt=1+(n-find(n))/2;
     printf("%lld",cnt);
    return 0;
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务