NewCoder-- 华为OJ题目详解(一)

来源:互联网 发布:php url 特殊字符转义 编辑:程序博客网 时间:2024/05/06 04:12

今天也算是第一天写CSDN博客,想跟你们一起讨论和解析一下牛客网华为OJ的题目,同时也能增进自己的算法能力。事不宜迟,我们开始吧!

1.字符串最后一个单词的长度
题目描述

计算字符串最后一个单词的长度,单词以空格隔开。

输入描述:
一行字符串,非空,长度小于5000。

输出描述:
整数N,最后一个单词的长度。

输入例子:
hello world

输出例子:
5

这是一道非常简单的题目,直接给代码吧–>–>

#include<iostream>#include<cstring>using namespace std;#define max 100000int main(){ int number=0,i,len;    char s[max];    gets(s);    len=strlen(s);    for(i=len-1;i>=0;i--)    {        if(s[i]==' ')        {            number=len-1-i;break;   #直观法,遇到空格则break        }    }    if(number!=0)cout<<number<<endl;    else   cout<<len<<endl;    return 0;}

2.计算字符个数
题目描述

写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。

输入描述:
输入一个有字母和数字以及空格组成的字符串,和一个字符。

输出描述:
输出输入字符串中含有该字符的个数。

输入例子:
ABCDEF
A

输出例子:
1

这道题也是一道非常简单的入门题,直接用数组可以实现,直接现代码吧–>

#include<iostream>#include<cstring>using namespace std;#define max 100000int main(){    char ch,s[max];int f=1,t[max];  #设置标志位    gets(s);memset(t,0,sizeof(t));    for(int i=0;i<strlen(s);i++)    {t[s[i]]++;}   #枚举每一位    cin>>ch;    for(int i=0;i<strlen(s);i++)    {        if(ch==s[i])        {f=0;            cout<<t[s[i]]<<endl;break;        }    }    if(f==1)cout<<"0\n"; #标志位,大于串长度输出"0"    return 0;}

3.明明的随机数

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

Input Param
n 输入随机数的个数
inputArray n个随机整数组成的数组

Return Value
OutputArray 输出处理后的随机整数

注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。

输入描述:
输入多行,先输入随机整数的个数,再输入相应个数的整数

输出描述:
返回多行,处理后的结果

输入例子:
11 10 20 40 32 67 40 20 89 300 400 15

输出例子:
10 15 20 32 40 67 89 300 400

这是一道数字去重和排序的问题.我的方法当然不是最好的,却是最直观的.先定义一个结果数组,初始化a[0]进行比较;然后依次输入其他值b进行直接插入排序,
最后输出。可是时间复杂度相对较高.

#include<iostream>#include<cstring>using namespace std;int main(){    int n,a[1000],b;            #定义a数组储存结果    while(cin>>n)   { cin>>a[0];int aLen=1;n--;  #先输入第一个数进行比较    while(n--)    {        cin>>b;                 #每次输入一位随机数进行比较        int i=0;        for(i=0;i<aLen;i++)     #遍历a数组            if(b==a[i]||b<a[i])break;        #使用直接插入法间接实现排序        if(b<a[i])      #小于的话,将b插入到a数组适合的位置(直接插入法)         {        for(int j=aLen-1;j>=i;j--)a[j+1]=a[j];            a[i]=b;            aLen++;        }        else if(b>a[i])      #大于的话,将b直接插入到a数组尾部,长度+1        {            a[aLen]=b;aLen++;        }    }    for(int j=0;j<aLen;j++)cout<<a[j]<<endl;      }    return 0;}

下面有个时间复杂度更优的解法,适合小数据:

#include <iostream>using namespace std;int main() {    int N, n;    while (cin >> N) {        int a[1001] = { 0 };  #每次使用前数组清零        //memset(a,0,sizeof(a));        while (N--) {            cin >> n;            a[n] = 1;  #每次输入一位标记一位,重复数字恒置         }        for (int i = 0; i < 1001; i++)            if (a[i])    #非零即输出                cout << i << endl;    }    return 0;}

后面的解法虽然简单直观,但是不提倡—>—>

4.字符串分隔

题目描述

•连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组;
•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。

输入描述:
连续输入字符串(输入2次,每个字符串长度小于100)

输出描述:
输出到长度为8的新字符串数组

输入例子:
abc
123456789

输出例子:
abc00000
12345678
90000000

这道题我定义了两个数组,一个源数组存储原来的数字,另一个储存输出的数字
实现数组间转移:够数则复制,不够则补0.

#include<iostream>#include<cstring>using namespace std;char *copy(char *dst,char *src,int n)    #这里我定义了两个数组指针,分别指向目标(输出)数组和源数组{ for(int i=0;i<n;++i){    if(src[i]) dst[i]=src[i]; #原数组里的值非零即转移保存     else dst[i]='0';         #为零的话补零 }      return dst;     #返回结果数组指针}int main(){ char buf[112]={0}; char out[9]={0};    while(gets(buf)){        char *p=buf;        while(*p){            cout<<copy(out,p,8)<<endl;                p+=8;        }        memset(buf,0,sizeof(buf));   #每次使用完清空数组    }}

5.进制转换
题目描述

写出一个程序,接受一个十六进制的数值字符串,输出该数值的十进制字符串。(多组同时输入 )

输入描述:
输入一个十六进制的数值字符串。

输出描述:
输出该数值的十进制字符串。

输入例子:
0xA

输出例子:
10
不解释上代码

#这种方法就是牛,打开世界的大门include <iostream>using namespace std;int main(){    int x;    while(cin>>hex>>x)        cout<<x<<endl;    return 0;}

当然进制转换还有很多的方法,我这里只是用了小技巧AC题目罢了

6.质数因子

输入一个正整数,按照从小到大的顺序输出它的所有质数的因子(如180的质数因子为2 2 3 3 5 )
最后一个数后面也要有空格

详细描述:

函数接口说明:
public String getResult(long ulDataInput)
输入参数:
long ulDataInput:输入的正整数
返回值:
String

输入描述:
输入一个long型整数

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

输入例子:
180

输出例子:
2 2 3 3 5

原理都是从最小的质数因子”2”下手,一步步增1,直到所有的质数因子全部输出

笔者曾经使用过python代码去AC

import syswhile True:    try:        number = long(sys.stdin.readline())        i = 2    while number != 1:            while number % i == 0:    #一直取余一直输出                print i,                       number = number / i             i = i + 1           #当前质数因子加1        print "",    except:        break

python代码是不是很简单?C++也挺简单的

#include<iostream>using namespace std;void change(int n){    int x=2;    while(x*x<=n){  #从2开始,每次进行平方        while(n%x==0){  #同理,一直取余一直输出            cout<<x<<" ";            n=n/x;        }        x++;    #当前质数因子加1    }    if(n>1)  cout<<n<<' ';   #输出格式控制}int main()    {    int n;    cin>>n;    change(n);    return 0;}

7.取近似值

题目描述

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

输入描述:
输入一个正浮点数值

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

输入例子:
5.5

输出例子:
6

这是道精度四舍五入处理的问题,笔者这里用到了C++ STL里的库函数 
—-> static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
  进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
  进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
百科地址:(可自行查阅)

static_cast

#include<iostream>using namespace std;int main(){    float x;   while(cin>>x){       if(x-static_cast<int>(x)>=0.5)           cout<<static_cast<int>(x)+1<<endl;          # 用法:static_cast < type-id > ( expression)       else cout<<static_cast<int>(x)<<endl;   }    return 0;}#该函数能够很好的保留精度

8.合并表记录

题目描述

数据表记录包含表索引和数值,请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出。

输入描述:
先输入键值对的个数
然后输入成对的index和value值,以空格隔开

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

输入例子:
4
0 1
0 2
1 2
3 4

输出例子:
0 3
1 2
3 4

因为要处理“键值对”问题,所以笔者这里用到了c++中的一个容器map
Map是c++的一个标准容器,提供了很好一对一的关系(键值对),在一些程序中建立一个map可以起到事半功倍的效果,它会自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
总结了一些map基本简单实用的操作!

#map的基本操作函数:      begin()          返回指向map头部的迭代器      clear()         删除所有元素      count()          返回指定元素出现的次数      empty()          如果map为空则返回true      end()            返回指向map末尾的迭代器      equal_range()    返回特殊条目的迭代器对      erase()          删除一个元素      find()           查找一个元素      get_allocator()  返回map的配置器      insert()         插入元素      key_comp()       返回比较元素key的函数      lower_bound()    返回键值>=给定元素的第一个位置      max_size()       返回可以容纳的最大元素个数      rbegin()         返回一个指向map尾部的逆向迭代器      rend()           返回一个指向map头部的逆向迭代器      size()           返回map中元素的个数      swap()            交换两个map      upper_bound()     返回键值>给定元素的第一个位置      value_comp()      返回比较元素value的函数

百度(可以自行查阅):键值对

不说这么多,直接上代码

#include<iostream>#include<map>using namespace std;int main(){    int n;while(cin>>n){        map<int,int>m;   #map容器        while(n--){            int key,value;            cin>>key>>value;            if(!m[key])m[key]=value;  #不同则建立            else m[key]+=value;   #相同则累加        }        for(map<int,int>::iterator it=m.begin();it!=m.end();++it){            #使用迭代器输出键值对            cout<<it->first<<" "<<it->second<<endl;        }    }    return 0;}

看吧。代码是不是相当简单呢

9.提取不重复的整数
题目描述

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

输入描述:
输入一个int型整数

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

输入例子:
9876673

输出例子:
37689

从右向左的阅读顺序读取数字去重,因为是数字,所以这里会涉及到一些数字处理的代码 num=num*10+n%10; #乘以位权再加上每步余数

#include<iostream>using namespace std;int main(){int n;int a[10]={0};int num=0;cin>>n;while(n){    if(a[n%10]==0) {     #取余表示从最右边读起        a[n%10]++;        num=num*10+n%10; #乘以位权再加上每步余数    }    n/=10;      } cout<<num<<endl; return 0;}

10.字符个数统计
题目描述

编写一个函数,计算字符串中含有的不同字符的个数。字符在ACSII码范围内(0~127)。不在范围内的不作统计。

输入描述:
输入N个字符,字符在ACSII码范围内。

输出描述:
输出范围在(0~127)字符的个数。

输入例子:
abc

输出例子:
3
这道题太直观了,怎么做都行

#include<iostream>using namespace std;int main(){    char ch;    int a[128]={0};    int cnt=0;    while(cin>>ch){        if(ch>=0&&ch<=127)a[ch]++;    }    for(int i=0;i<128;i++)    if(a[i]>0)cnt++;    cout<<cnt<<endl;}
#include<iostream>#include<string>using namespace std;int main(){    string x;    getline(cin,x);    int cnt=0;    for(int i=0;i<=127;++i)    if(x.find(i)!=string::npos)    cnt++;    cout<<cnt<<endl;    return 0;}
#include<iostream>#include<set>using namespace std;int main(){    char ch;    set<char>s;    while(cin>>ch)    {        if(ch>=0&&ch<=127)        s.insert(ch);    }    cout<<s.size()<<endl;    return 0;}

好了,今天就介绍十题给大家,不知不觉学了很多,欢迎大家讨论。

0 0
原创粉丝点击