牛客每日一题

牛客每日一题

1. HJ1 字符串最后一个单词的长度

字符串

在这里插入图片描述

答题技巧:cin输入的机制,有空格会停止,系统把空格作为数据间的分隔符,整个英文句子会一个单词一个单词的读。非常巧妙的使用了cin的读取逻辑。

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

int main(){
    string s;
    while(cin>>s);
    cout<<s.size();
    return 0;
}

好巧妙!!!

2. HJ2 计算某字符出现次数

在这里插入图片描述

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

int main(){
    string str;
    char ch;
    int count=0;
    getline(cin, str);
    cin>>ch;
    char res=tolower(ch);
        for(int i=0;i<str.size();i++){
              if(tolower(str[i])==res){
                count++;
               }      
        }      

    cout<<count;
    return 0;
}
一开始用cin输入字符串str,但是当字符串中有空格的时候,就会停止读取,答案错误,
所以改用了getline(),可以读取空格,答案正确。

3. HJ3 明明的随机数

题目描述
明明生成了NN个1500之间的随机整数。请你删去其中重复的数字,即相同的数字只保留一个,把其余相同的数去掉,然后再把这些数从小到大排序,按照排好的顺序输出。

数据范围: 1 \le n \le 1000 \1≤n≤1000  ,输入的数字大小满足 1 \le val \le 500 \1≤val≤500 
输入描述:
第一行先输入随机整数的个数 N 。 接下来的 N 行每行输入一个整数,代表明明生成的随机数。 具体格式可以参考下面的"示例"。
输出描述:
输出多行,表示输入数据处理后的结果

示例1
输入:
3
2
2
1
复制
输出:
1
2
复制
说明:
输入解释:
第一个数字是3,也即这个小样例的N=3,说明用计算机生成了31500之间的随机整数,接下来每行一个随机数字,共3行,也即这3个随机数字为:
2
2
1
所以样例的输出为:
1
2       

解法1:

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

int main(){
    int a,b;
    cin>>a;
    vector<int> str;
    for(int i=0;i<a;i++){
        cin>>b;
        str.push_back(b);
    }
    sort(str.begin(),str.end());
    auto new_start=unique(str.begin(),str.end());
    str.erase(new_start, str.end());

    for(auto num:str){
       cout<<num<<endl;
    }   
    return 0;
}

知识点

unique函数

unique函数属于STL中比较常用函数,它的功能是元素去重。即”删除”序列中所有相邻的重复元素(只保留一个)。此处的删除,并不是真的删除,而是指重复元素的位置被不重复的元素给占领了(详细情况,下面会讲)。由于它”删除”的是相邻的重复元素,所以在使用unique函数之前,一般都会将目标序列进行排序。

二.函数原型

unique函数的函数原型如下:

1.只有两个参数,且参数类型都是迭代器:

iterator unique(iterator it_1,iterator it_2);
这种类型的unique函数是我们最常用的形式。其中这两个参数表示对容器中[it_1,it_2)范围的元素进行去重(注:区间是前闭后开,即不包含it_2所指的元素),返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素。

unique函数的去重过程实际上就是不停的把后面不重复的元素移到前面来,也可以说是用不重复的元素占领重复元素的位置。

2.unique函数通常和erase函数一起使用,来达到删除重复元素的目的。(注:此处的删除是真正的删除,即从容器中去除重复的元素,容器的长度也发生了变换;而单纯的使用unique函数的话,容器的长度并没有发生变化,只是元素的位置发生了变化)关于erase函数的用法,可以参考:http://www.cnblogs.com/wangkundentisy/p/9023977.html。

erase函数:删除容器中从pos位置开始的n个元素。返回值是经过删除操作后的容器。

下面是一个具体的实例:

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

int main()
{
vector<int> a ={1,3,3,4,5,6,6,7};
vector<int>::iterator it_1 = a.begin();
vector<int>::iterator it_2 = a.end();
vector<int>::iterator new_end;

new_end = unique(it_1,it_2); //注意unique的返回值
a.erase(new_end,it_2);
cout<<"删除重复元素后的 a : ";
for(int i = 0 ; i < a.size(); i++)
    cout<<a[i];
cout<<endl;

}
这里,他的返回值是去重后序列(这个序列不含有重复数值)的末尾的下一个元素,在上边代码中,unique后,数组顺序为:1,3,4,5,6,7,X(代表重复数字,具体哪个不重要),X。他的返回值就是第一个重复数字的地址,所以,能用erase 实现彻底去重。

最后输出结果:

134567

解法2:

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

int main(){
    int n,a;
    cin>>n;
    set<int>nums;
    for(int i=0;i<n;i++){
        cin>>a;
        nums.insert(a);
    }

    for(auto num:nums){
        cout<<num<<endl;
    }
    return 0;
}

知识点

set

set就是集合,STL的set用二叉树实现,集合中的每个元素只出现一次(参照数学中集合的互斥性),并且是排好序的(默认按键值升序排列),访问元素的时间复杂度是O ( log ⁡2 n )。

for (auto x : nums)的作用:
相当于:
for (vector< int >::iterator iter = nums.begin(); iter != nums.end(); iter++)

for(auto a:b)中b为一个容器,效果是利用a遍历并获得b容器中的每一个值,但是a无法影响到b容器中的元素。
for(auto &a:b)中加了引用符号,可以对容器中的内容进行赋值,即可通过对a赋值来做到容器b的内容填充。

4. HJ4 字符串分隔

题目

描述
•输入一个字符串,请按长度为8拆分每个输入字符串并进行输出;

•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。
输入描述:
连续输入字符串(每个字符串长度小于等于100)

输出描述:
依次输出所有分割后的长度为8的新字符串

示例1
输入:
abc
复制
输出:
abc00000
复制
#include <string>
#include<iostream>
#include <vector>
using namespace std;

int main() {
   string str;
  while(cin>>str){
      int len=str.size();
      if(len%8!=0){
          int less=8-len%8;
          str.append(less,'0');

      }
      int newLen=str.size();
      for(int j=0;j<newLen;j+=8){
          cout<<str.substr(j,8)<<endl;
      }
  }
   return 0; 
}

substr(a,b):第一个参数a是要截取的字符串的起始位置,后一个参数b是要截取字符串的长度。

5. HJ5进制转换

描述
写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。

数据范围:保证结果在 1 \le n \le 2^{31}-1 \1≤n≤2 
311 
输入描述:
输入一个十六进制的数值字符串。

输出描述:
输出该数值的十进制字符串。不同组的测试用例用\n隔开。

示例1
输入:
0xAA
复制
输出:
170
复制

C语言中 %d 与 %i 的区别 和注意事项
在 printf 格式串中使用时,没有区别,输出都是十进制。

在 scanf 格式串中使用时,有点区别,如下:
——在scanf格式中,%d 只与十进制形式的整数相匹配。
——而%i 则可以匹配八进制、十进制、十六进制表示的整数。·
——例如: 如果输入的数字有前缀 0(018、025),%i将会把它当作八进制数来处理,如果有前缀0x (0x54),它将以十六进制来处理。

6. HJ6 质数因子

描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )


数据范围: 1 \le n \le 2 \times 10^{9} + 14 \1≤n≤2×10 
9
 +14 
输入描述:
输入一个整数

输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。

示例1
输入:
180
输出:
2 2 3 3 5

注意:该道题目比较简单,但是很容易超时,所以要找到合适的算法策略,结束条件是1=x/x。

#include<iostream>
#include <math.h>
using namespace std;

int main(){
    int num=0;
    cin>>num;
    int flag=num;
    if(flag==1){
        cout<<flag;
        return 0;
    }
     for(int i=2;i<=sqrt(flag);i++){
        if(flag%i==0){
            flag/=i;
            cout<<i<<" ";
            i=1;
        }
     }
    cout<<flag<<" ";
    return 0;
}

7. HJ7 取近似值

描述
写出一个程序,接受一个正浮点数值,输出该数值的近似整数值。如果小数点后数值大于等于 0.5 ,向上取整;小于 0.5 ,则向下取整。

数据范围:保证输入的数字在 32 位浮点数范围内
输入描述:
输入一个正浮点数值

输出描述:
输出该数值的近似整数值

示例1
输入:
5.5
复制
输出:
6
复制
说明:
0.5>=0.5,所以5.5需要向上取整为6   
示例2
输入:
2.499
复制
输出:
2
复制
说明:
0.499<0.52.499向下取整为2   
具体做法:
利用C++自带的强制类型转化可以将float转换成int,但是默认是向下取整,因此我们要给数字加上0.5,因为如果它原本小数部分小于0.5,加上0.5向下取整也是四舍,但是如果它原本小数部分大于等于0.5,加上0.5以后向下取整就是五入了。

在这里插入图片描述

解题
#include <iostream>
using namespace std;

int main(){
    double num;
    cin>>num;
    cout<<(int)(num+0.5);
    return 0;
}

8.HJ8 合并表记录

描述
数据表记录包含表索引index和数值value(int范围的正整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照index值升序进行输出。


提示:
0 <= index <= 11111111
1 <= value <= 100000

输入描述:
先输入键值对的个数n(1 <= n <= 500)
接下来n行每行输入成对的index和value值,以空格隔开

输出描述:
输出合并后的键值对(多行)

示例1
输入:
4
0 1
0 2
1 2
3 4
复制
输出:
0 3
1 2
3 4
复制
示例2
输入:
3
0 1
0 2
8 9
复制
输出:
0 3
8 9

解题

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

int main(){
     int n;
     cin>>n;
     map<int,int>m;
     map<int,int>::iterator it;
     for(int i=0;i<n;i++){
         int k,v;
         cin>>k>>v;
         it=m.find(k);
         if(it!=m.end()){
             m[k]=it->second+v;
         }else{
             m[k]=v;
         }

     }
    for(it=m.begin();it!=m.end();it++){
        cout<<it->first<<" "<<it->second<<endl;;
    }
    
    return 0;
}

知识点回顾:

  • Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

  • C++中map.find()函数

​ 函数原型:
​ iterator find (const key_type& k);
​ const_iterator find (const key_type& k) const;

​ 函数作用:
​ 在容器中寻找值为k的元素,返回该元素的迭代器。否则,返回map.end()。

9.HJ9 提取不重复的整数

知识点数组哈希

warning 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。

描述

输入一个 int 型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数。

保证输入的整数最后一位不是 0 。

数据范围: 1 \le n \le 10^{8} \1≤n≤108

输入描述:

输入一个int型整数

输出描述:

按照从右向左的阅读顺序,返回一个不含重复数字的新的整数

示例1

输入:

9876673

输出:

37689

解法:哈希表

#include<stdio.h>
int main(){
     int num,n;
     int hash[10]={0};
     scanf("%d",&n);
     while(n>0){
         num=n%10;
         n/=10;
         if(hash[num]==0){
             hash[num]=1;
             printf("%d",num);
         }
     }
    return 0;
}
#include<iostream>
#include<string>
#include<set>
using namespace std;

int main(){
  string str;
  set<char>s;
  int i=0;
  cin>>str;
  while(i<str.size()){
      s.insert(str[i]);
      i++;
  }
  cout<<s.size();
  return 0;
}

10.HJ10 字符个数统计

描述
编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0~127 ,包括 0127 ),换行表示结束符,不算在字符里。不在范围内的不作统计。多个相同的字符只计算一次
例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。

数据范围: 1 \le n \le 500 \1≤n≤500 
输入描述:
输入一行没有空格的字符串。

输出描述:
输出 输入字符串 中范围在(0~127,包括0127)字符的种数。

示例1
输入:
abc

输出:
3

示例2
输入:
aaa

输出:
1

方法1:哈希表

#include<stdio.h>

int main(){
    int hash[128]={0};
    char str[501];
    int i=0,count=0;
    gets(str);
    int len=strlen(str);
    for(int i=0;i<len;i++){
        int index=((int)str[i]);
        if(hash[index]==0){
            hash[index]=((int)str[i]);
            count++;
        }
    }
    printf("%d",count);
    return 0;
}

方法2:set

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

int main(){
  string str;
  set<char>s;
  int i=0;
  cin>>str;
  while(i<str.size()){
      s.insert(str[i]);
      i++;
  }
  cout<<s.size();
  return 0;
}

11、12题很简单,不做记录了。

13HJ13 句子逆序

描述
将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”

所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符

数据范围:输入的字符串长度满足 1 \le n \le 1000 \1≤n≤1000 

注意本题有多组输入
输入描述:
输入一个英文语句,每个单词用空格隔开。保证输入只包含空格和字母。

输出描述:
得到逆序的句子

示例1
输入:
I am a boy

输出:
boy a am I

示例2
输入:
nowcoder

输出:
nowcoder

解题:巧妙哭了呜呜呜

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

int main(){
    string str;
    string ans;
    while(cin>>str){
        ans=str+" "+ans;
    }
    cout<<ans;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值