企业编程题实战(一)

1、小v今年有n门课,每门都有考试,为了拿到奖学金,小v必须让自己的平均成绩至少为avg。每门课由平时成绩和考试成绩组成,满分为r。现在他知道每门课的平时成绩为ai ,若想让这门课的考试成绩多拿一分的话,小v要花bi 的时间复习,不复习的话当然就是0分。同时我们显然可以发现复习得再多也不会拿到超过满分的分数。为了拿到奖学金,小v至少要花多少时间复习。

在牛客上面没有通过,但是在本地运行的结果与牛客上的结果又是相同的,不知道是不是因为编译器的问题,有待之后进一步检查。
收获:对于sort函数的编写有了新的了解,其中第三个参数:cmp函数可以根据自己的要求进行编写,返回值是bool型,它规定了什么样的关系才是“小于”。

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

struct score_time {
    int score;
    int time;
};

int main() {
    int len, totals, avg;
    cin >> len >> totals >> avg;
    vector<score_time> s;
    score_time temp;
    int i = len;
    while (i > 0) {
        cin >> temp.score >> temp.time;
        s.emplace_back(temp);
        i--;
    }
    int need_score = avg * len;
    for (int i = 0; i < s.size(); i++) {
        need_score -= s[i].score;
        s[i].score = totals - s[i].score;
    }
    //定义sort函数比较规则
    //比较函数是一个自己定义的函数,返回值是bool型,它规定了什么样的关系才是“小于”
    //按照加一分需要的时间从小到大排序
    sort(s.begin(), s.end(), [](const score_time& a, const score_time& b)->bool {
        if (a.time == b.time) return a.score < b.score;
        else return a.time < b.time;
        });
    if (need_score <= 0) cout << 0 << endl;
    long min_time = 0;
    for (int i = 0; i < s.size(); i++) {
        if (need_score > s[i].score) {
            min_time += s[i].score * s[i].time;
            need_score -= s[i].score;
        }
        else {
            min_time += need_score * s[i].time;
            cout << endl;
            cout << min_time << endl;
            break;
        }
    }
    return 0;
}
2、计算字符串最后一个单词的长度,单词以空格隔开。

输入:Hello world! 输出:5
收获
在C++中本质上有两种getline函数:一种在头文件中,是istream类的成员函数;一种在头文件中,是普通函数。
1、 在中的getline()函数有两种重载形式:
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
作用是: 从istream中读取至多n个字符(包含结束标记符)保存在s对应的数组中。即使还没读够n个字符,如果遇到delim或 字数达到限制,则读取终止,delim都不会被保存进s对应的数组中。
2、第二种: 在中的getline函数有四种重载形式:
istream& getline (istream& is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream& is, string& str);
istream& getline (istream&& is, string& str);
用法和上第一种类似,但是读取的istream是作为参数is传进函数的。读取的字符串保存在string类型的str中。
函数的变量:
is :表示一个输入流,例如cin。
str :string类型的引用,用来存储输入流中的流信息。
delim :char类型的变量,所设置的截断字符;在不自定义设置的情况下,遇到’\n’,则终止输入。
getline不是C库函数,而是C++库函数。它遇到以下情况发生会导致生成的本字符串结束:(1)到文件结束,(2)遇到函数的定界符,(3)输入达到最大限度。

  • getline在while中作为条件判断,当如本例中getline(cin,str),当遇到换行时while循环结束,但是若** while (getline(cin, line,’#’))**则不一定跳出循环,因为while判断语句的真实判断对象是cin的状态,也就是判断当前是否存在有效的输入流。
#include<iostream>
#include<string>
using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        int len=0,flag=1;
        for(int i=str.size()-1;i>=0;i--){
            //从后往前计算,要是末尾有空格,首先清楚末尾的空格
            if(flag&&str[i]==' ') continue;
            else if(str[i]!=' '){
                flag=0;
                len++;
            }else break;
        }
        cout<<len<<endl;
    }
    return 0;
}
3、写出一个程序,接受一个由字母和数字组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。

收获: 看清题目要求,不区分大小写;
字母大小写转换:

  • 对应大小写字母之间相差32,大写+32=小写;
  • 利用toupper和tolower函数进行单个字母之间的大小写转换;
  • 利用strupr、strlwr函数进行整个字符串中字母的大小写转换;
  • 利用transform和tolower及toupper进行结合:
    transform(str.begin(),str.end(),str.begin(),tolower);
    transform(str.begin(),str.end(),str.begin(),toupper);
#include<iostream>
#include<string>
using namespace std;

int main(){
    string str;
    int times=0;
    while(getline(cin,str)){
        char tag;
        cin>>tag;
        for(int i=0;i<str.size();i++){
            if(tolower(str[i])==tolower(tag)) times++;
        }
    }
    cout<<times<<endl;
    return 0;
}
4、明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作(同一个测试用例里可能会有多组数据,希望大家能正确处理)。

收获:用空间换时间,将随机数作为数组的下标,然后顺序输出数组下标,即已经排序之后的结果。

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

int main(){
    int N,num;
    while(cin>>N){
        int a[1001]={0};
        while(N--){
            cin>>num;//重复数字作为a数组下标的那个元素只保留一个
            a[num]=1;
        }
        for(int i=1;i<1001;i++){
            if(a[i]) cout<<i<<endl;
        }
    }
    return 0;
}
5、连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组;长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。

收获:对两个函数的使用更加熟悉了:str.substr(pos,n);从pos开始连续n个字符子串,当超过pos范围,会作出out-of-range的异常
str.append(n,args);在str末尾添加n个args字符;str.append(args);在str末尾添加一个字符或者字符串。

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

int main(){
    string str;
    int N=2;
    while(N--){
        while(getline(cin,str)){
            int len=str.size();
            while(len>8){
                cout<<str.substr(str.size()-len,8)<<endl;
                len-=8;
            }
            str.append(8-len,'0');
            cout<<str.substr(str.size()-8,8)<<endl;
        }
    }
    return 0;
}
6、写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )

收获:while(cin>>hex>>a)可以连续输入a值

#include<iostream>
using namespace std;
int main(){
    int a;
    while(cin>>hex>>a){
        cout<<a<<endl;
    }
    return 0;
}
7、功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 ),最后一个数后面也要有空格

收获
1、判断从2到sqrt(n)是否存在其约数,时间复杂度O(sqrt(n));
2、判断2之后,就可以判断从3到sqrt(n)之间的奇数了,无需再判断之间的偶数,时间复杂度O(sqrt(n)/2);
3、大于等于5的质数一定和6的倍数相邻,在5到sqrt(n)中每6个数只判断2个,时间复杂度O(sqrt(n)/3);
4、0和1都不是质数。

#include<iostream>
#include<cmath>
using namespace std;
bool IsPrime(long num){
    if(num==1) return false;
    if(num==2||num==3) return true;
    if(num%6!=1&&num%6!=5) return false;
    float num_sqrt=floor(sqrt(num));
    //在5到sqrt(n)中每6个数只判断2个
    for(int i=5;i<=num_sqrt;i+=6){
        if(num%i==0||num%(i+2)==0) return false;
    }
    return true;
}
int main(){
    long num;
    cin>>num;
    if(num==1){
        cout<<" "<<endl;
        return 0;
    }
    while(!IsPrime(num)){
        if(num==1){
            cout<<endl;
            break;
        }
        for(int i=2;i<=floor(sqrt(num));i++){
            if(num%i==0){
                cout<<i<<" ";
                num/=i;
                break;
            }
        }
    }
    if(num!=1) cout<<num<<" "<<endl;
    return 0;
}
8、写出一个程序,接受一个正浮点数值,输出该数值的近似整数值。如果小数点后数值大于等于5,向上取整;小于5,则向下取整。

收获:floor() 向下取整(即最大不大于此数的整数);ceil() 向上取整(即最小不小于此数的整数);round() 四舍五入 取整

#include<iostream>
#include<cmath>
using namespace std;
int main(){
    float num;
    cin>>num;
    cout<<round(num)<<endl;
    return 0;
}
9、数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出。

输入:
4
0 1
0 2
1 2
3 4
输出:
0 3
1 2
3 4

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct record{
    int index;
    int num;
};
int main(){
    int len,i=0;
    cin>>len;
    vector<record> R(len);
    while(i<len){
        cin>>R[i].index>>R[i].num;
        i++;
    }
    if(len==0){
        cout<<endl;
        return 0;
    }
    if(len==1){
        cout<<R[len-1].index<<" "<<R[len-1].num<<endl;
        return 0;
    }
    sort(R.begin(),R.end(),[](const record&a,const record&b)->bool{
        if(a.index!=b.index) return a.index<=b.index;
        else return a.num<b.num;
    });
    for(int i=1;i<len;i++){
        int same_index_total=R[i-1].num;
        while(R[i].index==R[i-1].index&&i<len){
            same_index_total+=R[i].num;
            i++;
        }
        cout<<R[i-1].index<<" "<<same_index_total<<endl;
    }
    //当最后一个元素所以不等于倒数第二个元素索引时的处理
    //相等的情况已经在循环中处理了
    if(R[len-1].index!=R[len-2].index) cout<<R[len-1].index<<" "<<R[len-1].num<<endl;
    return 0;
}
10、输入一个int型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数。

输入:9876673 输出:37689
收获
map是STL的一个关联容器,它提供一对一的hash。
第一个称为关键字(key),每个关键字只能在map中出现一次;
第二个称为该关键字的值(value)。
插入关键字可以直接 Map[character]++;
查询map中某个关键字是否存在Map.count(character);等于0则不存在,等于1则存在

#include<iostream>
#include<map>
using namespace std;
int main(){
    int num;
    cin>>num;
    map<char,int> M;
    while(num%10==0){
        num/=10;
    }
    while(num>0){
        //不重复则输出
        if(!M.count(num%10)){
            cout<<num%10;
            M[num%10]++;
        }
        num/=10;
    }
    return 0;
}
11、编写一个函数,计算字符串中含有的不同字符的个数。字符在ACSII码范围内(0~127),换行表示结束符,不算在字符里。不在范围内的不作统计。多个相同的字符只计算一次。

收获
在这里插入图片描述

#include<iostream>
#include<string>
#include<map>
using namespace std;
int main(){
    string str;
    getline(cin,str);
    map<char,int> Map;
    int real_size=0;
    for(int i=0;i<str.size();i++){
        if(!Map.count(str[i])) {
            real_size++;
            Map[str[i]]++;
        }
    }
    cout<<real_size<<endl;
    return 0;
}
12、将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符

收获:当主循环退出条件和i相关(判断下标是否越界),同时在主循环中的子循环退出条件也和i相关的时候,要注意子循环中也要判断i是否越界。

#include<iostream>
#include<string>
using namespace std;
int main(){
    string str;
    string temp;
    getline(cin,str);
    int i=str.size()-1;
    while(i>=0){
        int len=0;
        while(str[i]!=' '&&i>=0){
            len++;
            i--;
        }
        temp+=(str.substr(i+1,len)+' ');
        i--;
    }
    cout<<temp<<endl;
    return 0;
}
13、密码要求:1.长度超过8位; 2.包括大小写字母.数字.其它符号,以上四种至少三种;3.不能有相同长度大于2的子串重复

收获:可以将重复功能的代码分离出一个函数;同时在最后判断三个条件的时候,若不符合可以列出子条件,这样的话有一个条件不符合就可以提前退出判断,减少运行时间,同时在

#include<iostream>
#include<string>
using namespace std;
string Password_Vertification(string str) {
    int len=str.size();
    int tag[4] = { 0 };
    for (int i = 0; i < len; i++) {
        if (str[i]>='A'&&str[i]<='Z') tag[0] = 1;
        else if (str[i]>='a'&&str[i]<='z') tag[1] = 1;
        else if (str[i]>='0'&&str[i]<='9') tag[2] = 1;
        else  tag[3] = 1;
        //若增加这一句的话会超出运行时间,因为每次都要计算一下tag种元素的总和
        //if (tag[0] + tag[1] + tag[2] + tag[3] >= 3) break;
    }

    bool flag = false;
    for (int i = 0; i <= len - 6; i++) {
        for (int j = i + 3; j <= len-3; j++) {
            if (str[i] == str[j] && str[i + 1] == str[j + 1] && str[i + 2] == str[j + 2]) {
                flag = true;
                break;
            }
        }
        if (flag == true) break;
    }
    if (len >= 9 && (tag[0] + tag[1] + tag[2] + tag[3] >= 3) && flag == false) return "OK";
    else if (len <= 8 || (tag[0] + tag[1] + tag[2] + tag[3] <= 2) || flag == true) return "NG";
}

int main() {
    string str;
    while (getline(cin, str)) {
        cout << Password_Vertification(str) << endl;
    }
    return 0;
}
14、实现删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。注意每个输入文件有多组输入,即多个字符串用回车隔开

输入描述:字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。
收获:当已知输入的字符数量范围或字母的范围可以考虑用空间换时间。

#include<iostream>
#include<string>
using namespace std;
string Del_str(string str){
    string temp;
    int a[26]={0};
    int len=str.size();
    int min=str.size();
    for(int i=0;i<len;i++){
        a[str[i]-'a']+=1;
    }
    for(int i=0;i<26;i++){
        if((a[i]<=min)&&(a[i]!=0)){min=a[i];}
    }
    for(int i=0;i<len;i++){
        if(a[str[i]-'a']>min){
            temp+=str[i];
        }
    }
    return temp;
}
int main() {
    string str;
    while(cin>>str){
        cout<<Del_str(str)<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值