牛客-模拟、枚举、贪心 2022.11.12

字符串

滑动窗口,写判定当前子串是否包含所有的字母

#include <bits/stdc++.h>
using namespace std;
int num[26] = {0};
bool bingo() {
    for(int i = 0; i < 26; i++) {
        if(num[i] == 0)
            return false;
    }
    return true;
}
int main() {
    memset(num, 0, sizeof(num));
    string s;
    cin >> s;
    int start = 0, res = INT_MAX;
    for(int i = 0; i < s.size(); i++) {
        num[s[i] - 'a'] += 1;
        if(bingo()) {
            res = min(res, i - start + 1);
            while(start < i) {
                num[s[start] - 'a'] -= 1;
                start += 1;
                if(!bingo())
                    break;
                res = min(res, i - start + 1);
            }
        }
    }
    cout << res << endl;
    return 0;
}

加减

对数组数据按照从小打大排序,前缀和记录相邻数据之间的差值,经过k次操作如果需要相同数据出现的次数最多,那么肯定是变化为数组中已经存在的数字,以当前数组位置作为左端点,二分求解右端点的位置。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
long long f[maxn];
long long delta[maxn];
long long k;
bool judge(int l,int r) {
    int mid = (l + r)>>1;
    //处于[l, mid]区间的所有数变成mid需要的操作数
    long long left = f[mid] * (mid - l + 1) - (delta[mid] - delta[l-1]);
    //处于[mid + 1, r]区间的所有数变成mid需要的操作数
    long long right =  (delta[r] - delta[mid]) - (r - mid) * f[mid];
    long long ans = left + right;
    return ans <= k ? true : false;
}
int main() {
    int n;
    cin >> n >> k;
    for(int i = 1; i <= n; i++)
        cin >> f[i];
    sort(f + 1, f + n + 1);
    for(int i = 1; i <= n; i++)
        delta[i] = delta[i - 1] + f[i];
    int res = 0;
    for(int i = 1; i <= n; i++) {
        int l = i, r = n;
        while(l < r) {
            int mid = (l + r + 1)>>1;
            if(judge(i, mid))
                l = mid;
            else
                r = mid - 1;
        }
        res = max(res, r - i + 1);
    }
    cout << res << endl;
    return 0;
}

牛牛的木板

第一遍写的思路是:统计连续的1和0的个数,1的个数为正数记录,0的个数为负数记录,之后遍历连续数组每个位置,以当前位置为起点,寻找最后的端点。但是总是超时,于是考虑能否二分,但是二分其实判定的函数时间复杂度也是O(n).之后再想,其实不需要做一个连续化,直接在原本数组上进行滑动窗口操作,即可判定。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int 
     * @param m int 
     * @param a intvector 
     * @return int
     */
    int solve(int n, int m, vector<int>& a) {
        // write code here
        int res = 0, sum = 0, start = 0, end = 0;
        while(end < a.size()) {
            while(end < a.size()) {
                if(a[end] == 1)
                    sum = sum + 1;
                else {
                    if(m > 0) {
                        m -= 1;
                        sum = sum + 1;
                    } else
                        break;
                }
                end = end + 1;
            }
            res = max(res, sum);
            while(start < a.size() && m <= 0) {
                if(a[start] == 1) {
                    sum -= 1;
                } else {
                    m += 1;
                    sum -= 1;
                }
                start += 1;
            }
        }
        return res;
    }
};

丢手绢

滑动窗口,由于顺逆时针,所以数组元素要存储两遍,进行前后拼接形成循环

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    vector<int> p;
    int sum = 0;
    for(int i = 0; i < n; i++) {
        int a;
        cin >> a;
        p.emplace_back(a);
        sum = sum + a;
    }
    int res = INT_MIN;
    for(int i = 0; i < n; i++)
        p.emplace_back(p[i]);
    int start = 0, end = 0, sum1 = 0;
    while(end < p.size()) {
        while(end < p.size()) {
            sum1 = sum1 + p[end];
            res = max(res, min(sum - sum1, sum1));
            end += 1;
            if(sum1 * 2 >= sum)
                break;
        }
        res = max(res, min(sum - sum1, sum1));
        while(start < p.size() && sum1 * 2 >= sum) {
            sum1 -= p[start];
            start += 1;
        }
    }
    cout << res << endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牛客 a卷2022年第四季度的华为题目中,要求考生设计一种高效的数据结构,能够支持以下几种操作: 1. 添加一个元素 2. 删除一个元素 3. 查找是否存在某个元素 4. 返回元素的总数 该数据结构要求满足空间复杂度较小、时间复杂度较低、能够快速地进行查找和修改等多种操作。 想要编写这样一种数据结构,我们可以参考许多已有的经典算法与数据结构,如二叉树、哈希表、红黑树等,通过综合利用它们的优点来实现这个问题的解决。 例如,我们可以通过哈希表来存储所有元素的值,并在每个哈希链表的元素中再使用红黑树来进行排序与查找。这样,我们既能够轻松地进行元素的添加和删除操作,也能够在查找较大数据范围和数量时保持较高的速度与效率。同时,由于使用了多个数据结构来协同完成这个问题,我们也能够在空间复杂度上适度地进行优化。 当然,在具体设计这个数据结构的过程中,我们还需要考虑一些实践中的细节问题,例如如何避免哈希冲突、如何处理数据丢失与被删除元素所占用的空间等问题,这都需要相应的算法与流程来进行处理。 总体来看,设计这种支持多种操作的高效数据结构,需要我们具备丰富的算法知识和编程实践能力,同时需要我们在具体处理问题时能够将多种算法和数据结构进行有效地结合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值