【每日训练】组队竞赛&&删除公共字符

目录

1.组队竞赛: 

        题目链接:

        输入输出&&测试用例:

        解析:

        程序:

2.删除公共字符串:

        题目链接:

         输入输出&&测试用例:

        解析: 

        程序:


1.组队竞赛: 

        题目链接:

        组队竞赛__牛客网 (nowcoder.com)

        输入输出&&测试用例:

 输入:                                输出:

2                        10
5 2 8 5 1 5

        解析:

题目描述:        

        首先在输入的3*n个人中每三人一组。其次,每一组取第二高值为此组的平均值。根据样例可以看到存在相同的如果是在前面(第一大)就取大的那个(ed:3 2 3,取3)相等的自然不用多说。现在输入一组3*n的数,想让我们如何分组求所有组的平均值加起来最大。

思路

        描述中的第二大非常关键。既然我们输入了一组数,如果能对其进行排序呢?

        比如上面的测试用例中,我们对其排序,这样就可以较为直观的看到数据之间的大小关系:

        1 2 5 5 5 8

        实际上,想要每组相加的平均值最大,可以缩小到将每组的第二大控制到最大。那么我们能否将上面由小到大排序好的数组从右端挑选两个和左端挑选一个呢?这样就能保证右端挑选的两个每次是在未分组数据中保证第二大数据是最大的。这样分好组后就能控制平均值最大。

        ed:

        1        5 8        -> 5

        2        5 5        -> 5

        上面测试用例的组已经分完,此时两个组平均值相加即为这一列数据中最大的。

        程序:

        有了上面的思路后,编程的目标就是找到这一组数据中的中间值并且相加。

        首先排序,那么中间值如何找呢?我们可以利用1 2 3 4 5 6 7 8 9 这一组数据进行抽象整理:

下标:0 1 2 3 4 5 6 7 8

数据:1 2 3 4 5 6 7 8 9

        数据长度:9

        第一组平均值:8        9 - 2(这里计算的是8对应的下标值,下面同理)

        第二组平均值:6        9 - 4

        第三组平均值:4        9 - 6

        可以抽象得到:每组第二大下标 = 数组长度 - 2 * 组数   

(需要注意牛客网后台测试可能是循环输入,所以最好将程序改为循环输入最佳)  

#include <iostream>
#include <algorithm>  // 算法头文件
#include <vector> // 根据n进行变化的数组
using namespace std;

int main()
{
    long long n = 0, maxi = 0;  // 组长    输出的这一组的组平均值最大
    vector<int> v;
    while (cin >> n)  // 注意控制成循环输入
    {
        v.resize(3 * n);  // 给数组开对应的数据长度
        for (int i = 0; i < 3 * n; ++i)
        {
            cin >> v[i];
        }
        sort(v.begin(), v.end());  // sort进行排序,底层为快速排序
        for (int i = 0; i < n; i++)  // 利用上面我们抽象出来的公式进行计算
        {
            maxi += v[v.size() - 2 * (i + 1)];  // 别忘了 + 1
        }
        
        cout << maxi << endl;  // 输出
        maxi = 0;  // 每次循环记得清空
    }
    return 0;
}

        注意存储数据改为long long,否则int类型数据会发生截取,导致不正确

2.删除公共字符串:

        题目链接:

删除公共字符_牛客题霸_牛客网 (nowcoder.com)

         输入输出&&测试用例:

 

        解析: 

题目描述

        首先输入两个字符串(注意有空格),输出从第一个字符串删除所有的第二个字符串中所有相同字符的字符串。

思路

        根据第二个字符串的所有字符去删除,首先第二个字符串肯定是要遍历的,那么是不是在遍历的同时去删呢?可以,只不过这样就相当于嵌套了一个循环,时间复杂度为O(n^2)效率低下。

        那么我们可不可以只遍历一遍第一个字符串就能删完呢?

        这就要用到哈希或者key-value思想了。我们可以定义一个数组。因为是字符串,即都为字符char,所以这个数组就可以定义大小为256。因为一个字符对应一个ASCII码值,那么我们能否以此为下标通过遍历一遍第二个字符串将第二个字符串的每个字符出现次数记录一遍呢?这样我们在遍历第一个字符串的时候出现此时为0是否就可以不用删除呢?

        程序:

        首先输入两个字符串,由于存在空格,所以普通的输入不行(scanf()或者cin),C++可以利用getline进行输入。创建一个数组记录第二个字符串每个字符出现次数。

        创建一个新的字符串,这样遍历第一个字符串的时候,当前字符出现次数为0就可以进行尾插。输出此新字符串。

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

int main()
{
    string str1, str2;
    getline(cin, str1);
    getline(cin, str2);
    int arr[256] = {0};  // 全体初始化为0

    for (int i = 0; i < str2.size(); i++)  // 遍历一遍第二个字符串统计每个字符出现个数
    {
        arr[str2[i]]++;
    }
    string str;  // 新字符串,用来保存删除后的str1
    for (int i = 0; i < str1.size(); i++)
    {
        if (!arr[str1[i]]) str += str1[i];  // 为0表示在第二个字符串没有存在,不用删除
    }
    cout << str << endl;
    return 0;
}

        训练员今天也要加油呀~ 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值