阿里编程题2021.8.27+招银科技测开2021.9.6

1、最小的最大值
牛牛有一个长度为n的正整数数组a={a1,a2,…,an},现在他可以执行下面的操作:
选择一个i(1<=i<=n),令ai=ai+1
必须执行k次上述的操作,牛牛想让执行完所有操作之后的数组a中的最大值尽可能的小,请你帮助牛牛计算这个尽可能小的最大值。

示例1:
输入:
3 3
1 2 3
输出:
3
说明:
第1次操作:选择a1,令a1=a1+1=2,数组为{2,2,3}
第2次操作:选择a1,令a1=a1+1=3,数组为{3,2,3}
第3次操作:选择a2,令a2=a2+1=3,数组为{3,3,3}

示例2:
输入:
3 6
1 2 3
输出:
3
说明:
前3次操作同例1,数组变为{3,3,3}
接下来3次操作依次选择a1,a2,a3,最终数组变为{4,4,4},因此答案为4。

思路:每次在最小的数上进行加1操作。
(1)当所有与最大数的差之和大于或等于要操作的次数k时:最后的最大值就是初始最大值。因为,还未达到把所有的数变为一样。
(2)当所有与最大数的差之和小于要操作的次数k时:在没达到要操作的次数k之前,已经将所有的数变为一样;剩余的次数(k-sum),平均分配给每个数即可。这样最后的最大值就是(初始最大值+剩余次数 / 数组个数的向上取整)
原始版:

#include <iostream>
#include <cmath>	// ceil()向上取整的所在头文件
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n,k;
    cin>>n>>k;
    vector<int> inputs(n);
    for(int i=0;i<n;i++){
        cin>>inputs[i];
    }
    sort(inputs.begin(),inputs.end());
    float sum=0;
    for(int i=0;i<n;i++){
        sum+=inputs[inputs.size()-1]-inputs[i];
    }
    if(k<=sum){
        cout<<inputs[inputs.size()-1]<<endl;
    }
    else if(k>sum){
        float j=k-sum;
        float m=inputs.size();
        int res = ceil(j/m);
        cout<<inputs[inputs.size()-1] + res<<endl;
    }
    return 0;
}
// 只通过52%

注意:要考虑数据溢出情况————用long类型(长整型)!!!!!
x/y向上取整 等价于 (x+y-1)/y向下取整
修改版:

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

int main() {
    int n;
    long k;
    cin>>n>>k;
    vector<long> inputs(n);
    for(int i=0;i<n;i++){
        cin>>inputs[i];
    }
    sort(inputs.begin(),inputs.end());
    long max = inputs[n-1];
    long sum=0;
    for(int i=0;i<n;i++){
        sum += max-inputs[i];
    }
    
    if(k>sum){
        k=k-sum;
        max+=(k+n-1)/n;	//实现向上取整
    }
    cout<<max<<endl;
    return 0;
}

2、集合
牛牛的k支部队驻扎在一个 n * m 的矩形地图上,每只部队都驻扎在一个独一无二的坐标(i,j)(1<=i<=n,1<=j<=m)上(i,j都是整数)。
对于每一支部队,假设该部队当前的坐标为(i,j),则该部队可以花费1小时从坐标(i,j)移动到(i+1,j),(i,j+1),(i-1,j),(i,j-1)这四个坐标的其中一个(即每次可向上、下、左、右移动),且该部队不能离开地图。
地图上还有一些整数坐标是沼泽,部队不能达到沼泽区域
现在牛牛要将这些部队集结到同一个坐标点集结总耗时为到达集结点最慢的部队的耗时,牛牛想知道集结总耗时最短需要几小时
输入描述:
第一行输入两个正整数 n, m 表示矩阵地图的长和宽
接下来 n 行每行输入一个长度为 m 的只包含 ‘0’ 和 ‘1’ 的字符串,如果第 i 行第 j 列的字符为‘1’,则表示坐标(i,j)为沼泽,如果第 i 行第 j 列的字符为‘0’,则表示坐标(i,j)为陆地(部队只能在陆地上,儿不能在沼泽上)。
接下来一行输入正整数 k 表示部队的数目
最后 k 行每行两个正整数 x,y表示部队驻扎的坐标为(x,y)
(1<=n,m<=500,1<=k<=min(10,n*m-S),1<=x<=n,1<=y<=m,其中S为沼泽区域的个数,数据保证初始部队的坐标不会和沼泽的坐标重合。)
输出描述:
输出一个正整数表示集结总耗时最短需要几个小时,如果所有的部队无法集结到一块,则输出-1。

示例1:
输入:
3 3
000
101
000
4
1 1
1 3
3 1
3 3
输出:
2
说明:部队从(1,1),(1,3),(3,1),(3,3)出发到(2,2)耗时均为2,最终集合时间为2,因此答案为2。

示例2:
输入:
3 3
000
111
000
2
1 2
3 2
输出:
-1
说明:两支队伍无法集合在一起。

思路:每个军队同时做广度优先遍历,看是否能够聚集在一起?
首先求每个军队到达地图任何一个地方的最短时间,然后遍历所有地点,计算所有军队到达这里的最大值,这些最大值中的最小值即为所求。

招银科技测开

1、题目:将一个数组按照1,2,3…递增的顺序用逗号分隔,如果最后剩余的个数不足以进行分隔,则省略。

例1:[1 2 3 4 5 6]
输出[1],[2 3],[4 5 6]
例2:[1 2 3 4]
输出:[1],[2 3]

思想:
1、记录 j 为递增序列中的每一项,初始为1;
2、循环遍历数组:
如果剩余的元素个数 < 当前要分隔的个数,则结束循环;
将当前要分隔的数存放在一个数组中。将遍历的下标通过加 j,移动到下次要分隔的位置。

#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> get_in(vector<int>&L){
    vector<vector<int>> result;
    int j=1;
    int n=L.size();
    for(int i=0;i<n;){
        if(n-i-j<0) break; //!!!笔试时是写错了。心塞
        int k=0;
        vector<int> tmp;
        while(k<j){
            tmp.push_back(L[i+k]);
            k++;
        }
        result.push_back(tmp);
        i += j;
        j++;
    }
    return result;
}
int main() {
    vector<int> inputs;
    int x;
    while(cin>>x){
       inputs.push_back(x); 
    }
    vector<vector<int>> res = get_in(inputs);
    for(int i=0;i< res.size();i++){
        cout << "[";
        for(int j=0;j<res[i].size();j++)
            cout<<res[i][j]<<",";
        cout<<"]";
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值