微软 笔试 8.13

1、最少垃圾处理站数

数组表示所有垃圾点垃圾数,每次处理站可以减少某个站一半,需要减少到总量的一半以下,求嘴上的站数。
思路:大顶堆排序,每次顶除二再重排

void heapify(vector<double>& arr, int n, int i)
{
    if (i > n) {
        return;
    }
    int left = i*2+1;
    int right = i*2+2;
    int max_index = i;
    if (left < n && arr[left] >= arr[max_index]) {
        max_index = left;
    }
    if (right < n && arr[right] >= arr[max_index]) {
        max_index = right;
    }
    if (max_index != i) {
        swap(arr[i], arr[max_index]);
        heapify(arr, n, max_index);
    }
}
 
void buildHeap(vector<double>& arr)
{
    int n = (int)arr.size();
    for (int i = (n-2)/2; i >= 0; i--)
    {
        heapify(arr, n, i);
    }
}


int solution(vector<int> A) {
    vector<double> arr(A.size(), 0);
    double sum = 0;
    for (int i=0; i<A.size(); i++) {
        sum += A[i];
        arr[i] = A[i];
    }
    buildHeap(arr);
    double now_sum = 0;
    int res = 0;
    while (now_sum*2 < sum) {
        now_sum += arr[0]/2;
        arr[0] = arr[0]/2;
        heapify(arr, arr.size(), 0);
        res++;
    }
    return res;
}

2、分数求和为1
两个数组A和B,表示所有分数依次分子和分母。求有多少种可能,任取两个相加和为1
思路:哈希表+gcd

int gcd(int a, int b){
    while (b) {
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}

int solution(vector<int> &X, vector<int> &Y) {
    map<string, int> mp;
    int res = 0;
    int MOD = 1000000007;
    for (int i=0; i<X.size(); i++) {
        int a = X[i], b = Y[i];
        int tmp = gcd(a,b);
        a = a/tmp;
        b = b/tmp;
        string key = to_string(a) + "/" + to_string(b);
        string other = to_string(b-a) + "/" + to_string(b);
        if (mp.find(other) != mp.end()) {
            res += mp[other];
            res %= MOD;
        }
        if (mp.find(key) == mp.end()) {
            mp[key] = 1;
        } else {
            mp[key]++;
        }
    }
    return res;
}

3、康复训练
病人做康复训练,共需要做X次。一共有n天可以选择,每次耗费为A[i]。每次完成训练后必须在Y天后继续训练,求最小成本。
思路:前缀和,分组
 

int solution(vector<int>& A, int X, int Y) {
    vector<int> preSum(A.size()+1, 0);
    for (int i=0; i<A.size(); i++) {
        if (i+1-Y >= 0) {
            preSum[i+1] = A[i] + preSum[i+1-Y];
        } else {
            preSum[i+1] = A[i];
        }
    }
    int res = INT_MAX;
    for (int i=(X-1)*Y+1; i<=A.size(); i++) {
        int tmp = 0;
        if (i < X*Y) {
            tmp = preSum[0];
        } else {
            tmp = preSum[i - X*Y];
        }
        if (res > preSum[i] - tmp) {
            res = preSum[i] - tmp;
        }
    }
    return res;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值