「算法刷题」牛客华为题库(一)

[TOC]

​ 华为机试题库共103道题目,其中入门级5道,简单级46道,中等级36道,较难级13道,困难级3道。

相关的API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//将一个字符串中的字符全部转换为小写:
for (int i = 0; i < str.length(); i++)
{
if ('A' <= str[i] && str[i] <= 'Z')
str[i] += 32;
}
// 将一个字符转换为小写:
char c=tolower(ch);
// 在字符串末尾添加n个字符
str.append(n, '0');
// 根据索引获取字符串的子串
int len = str.size();
for (int i = 0; i < len; i += 8){
cout << str.substr(i, 8) << endl;
}
// 分割字符串
char s[]= "Golden~Global_View,disk*desk";//待分割的字符数组
const char *d = "~ ,*";// 分割字符集合
char *p;
p = strtok(s,d);//s必须是char[] 类型
while(p)
{
printf("%s\n",p);
p=strtok(NULL,d);
}

// 将n进制的字符串转换为十进制
#include <string>
int stoi(str,x,n)//将 n 进制的str从索引x开始转化为十进制的整数

// 字符串转换为char []
char ch[20];
string s="123456";
strcpy(ch,s.c_str());

一、入门级

HJ46 截取字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<string>
using namespace std;

int main(){
// 获取输入
string s;
getline(cin,s);
int k;
cin>> k;
// 返回结果
cout<<s.substr(0,k);
return 0;
}

HJ 58 输入n个整数,输出其中最小的k个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int main(){
int n,k;
cin>>n>>k;
int temp;
vector<int> arr;
while(n--){
cin>>temp;
arr.push_back(temp);
}
sort(arr.begin(),arr.end());
for(int i=0;i<k;i++){
cout<<arr[i]<<" ";
}
return 0;
}

HJ101 输入整型数组和排序标识,对其元素按照升序或降序进行排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
#include<vector>
#include<bits/stdc++.h>
using namespace std;

bool cmp(int a,int b){
return a>b;
}
int main(){
int n;
cin>>n;
vector<int> arr;
int i;
while(n--){
cin>>i;
arr.push_back(i);
}
int b;
cin>>b;
if(b==0){
sort(arr.begin(),arr.end());
}
else if(b==1){
sort(arr.begin(),arr.end(),cmp);
}

for(int i=0;i<arr.size();i++){
cout<<arr[i]<<' ';
}
return 0;
}

二、简单级

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
#include<string>
using namespace std;

int main(){
// 获取输入
string input;
getline(cin,input);
// 计算结果
int res=0;
// 从最后一个字符向前走
int i=input.length()-1;
while(i>=0&&input[i]!=' '){
res++;
i--;
}
cout<<res;
return 0;
}

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

题目要求不区分字母大小写

方法一:将目标字符和字符串中的每个字符都转换为小写后遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>

using namespace std;
int main(){
// 获取输入
string s;
getline(cin, s);//不用cin,因为cin默认截断符是空格,tab,enter等空白字符。有个用例的字符串中包含空格
char c;
cin>>c;
// 计算结果
c=tolower(c);
int res = 0;
for (char i : s) {
if (tolower(i) == c) {
++res;
}
}
cout <<res;
}


方法二:转换为小写加入哈希表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;

int main()
{
// 获取输入
string s;
getline(cin, s);
char c;
cin>>c;
// 计算结果
c=tolower(c);
//在声明诸如字符数或者数组索引这样的长度变量时用size_t 是好的做法。size_t 类型表示C/C++中任何对象所能达到的最大长度,它是无符号整数。
unordered_map<char, size_t> dict;
for (auto i : s) {
++dict[tolower(i)];
}
cout << dict[tolower(c)] << endl;
}

3、HJ4 字符串分隔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<string>
using namespace std;

int main(){
string str;
getline(cin,str);

int len=str.size();

if(len%8!=0){
int count=8-len%8;
str.append(count,'0');
}
//此时字符串长度是8的倍数,每8个字符输出即可
int newLen=str.size();
for(int i=0;i<newLen;i+=8){
cout<<str.substr(i,8)<<endl;
}
return 0;
}

4、HJ5 进制转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
#include<math.h>
#include<string>
using namespace std;

int main(){
string s; //0xAA
cin>>s;
// 方法一:cout<<stoi(s,0,16)<<endl;
int n=s.size();
int res=0;
// 从后向前遍历,0x不用转换,忽略即可
for(int i=n-1;i>1;i--)
{
int cur=0;
// 如果当前数是0-9,则res+=n^(n-i-1)
if(s[i]>='0'&&s[i]<='9'){
cur=s[i]-'0';
}
// 如果当前数是A-F,则res+=n^(n-i-1)
if(s[i]>='A'&&s[i]<='F'){
cur=s[i]-'A'+10;
}
res+=cur*pow(16,n-i-1);
}
cout<<res<<endl;
return 0;
}

5、HJ10 字符个数统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;
int main(){
string s;
cin>>s;
unordered_map<int,int> dict;
for(char c:s){
dict[c]++;
}
cout<<dict.size()<<endl;
return 0;
}

6、HJ8 合并表记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
#include<map>
using namespace std;

int main(){
int n;
cin>>n;
map<int,int>dict;
while(n--){
int key,value;
cin>>key>>value;
dict[key]+=value;
}
for(auto kv:dict){
cout<<kv.first<<" "<<kv.second<<endl;
}
return 0;
}

7、HJ12 字符串反转

直接用函数进行字符串反转

1
2
#include<algorithm>
reverse(s.begin(),s.end());

考察自己写字符串反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include<string>
using namespace std;

int main(){
string s;
getline(cin,s);

int i=0,j=s.length()-1;
while(i<j){
swap(s[i],s[j]);
i++;
j--;
}
cout<<s;
return 0;
}

8、 HJ13 句子逆序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
#include<algorithm>
using namespace std;

//逆序字符串
void reverseStr(string &str,int start,int end){
int left=start;
int right=end;
while(left<right)swap(str[left++],str[right--]);
}
//字符串中每个单词拿出来,并将每个单词逆序
void split(string &str){
int left=0;
int len=str.length();
while(left<len){
while(left<len&&str[left]==' ')left++;
int right=left;
while(right<len&&str[right]!=' ')right++;
reverseStr(str,left,right-1);
left=right;
}
}
int main(){
//获取输入
string s;
while(getline(cin,s)){
//字符串中每个单词拿出来,并将每个单词逆序
split(s);
//整体都逆序
reverse(s.begin(),s.end());
cout<<s;
}
return 0;
}

9、 HJ106 字符逆序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
#include<string>
using namespace std;

void reverseStr(string &str,int start,int end){
int left=start;
int right=end;
while(left<right)swap(str[left++],str[right--]);
}
int main(){
string s;
getline(cin,s);
reverseStr(s,0,s.length()-1);
cout<<s;
return 0;
}

10、HJ14 字符串排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int main(){
string s;
int k;
cin>>k;
vector<string> arr;
while(k--){
cin>>s;
arr.push_back(s);
}
//按照字典序排列的字符串。sort需要头文件#include<algorithm>
sort(arr.begin(),arr.end());
for(int i=0;i<arr.size();i++){
cout<<arr[i]<<endl;
}
return 0;
}

11、 HJ31 单词倒排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;

void reverseStr(string &str,int start,int end){
int left=start;
int right=end;
while(left<right){
swap(str[left++],str[right--]);
}
}

void split(string &str,vector<string> &arr){
int left=0;
int len=str.length();
while(left<len){
// left找到了第一个英文字符
while(str[left]==' '&&left<len)left++;
int right=left;
// right找到单词后的第一个空格
while(str[right]!=' '&&right<len)right++;
//[left,right-1]
arr.push_back(str.substr(left,right-left));
//reverseStr(str,left,right-1);
left=right;
}
}

bool is_A(char c){
if(c>='A'&&c<='Z')return true;
return false;
}

bool is_a(char c){
if(c>='a'&&c<='z')return true;
return false;
}

void update(string &str){
for(int i=0;i<str.size();i++){
if(!isalpha(str[i])) str[i]=' ';
//if(!is_A(str[i])&&!is_a(str[i]))str[i]=' ';
}
}
int main(){
// 获取输入
string s;
getline(cin,s);
// 将所有的间隔符统一替换为空格
update(s);
// 分割
vector<string> arr;
split(s,arr);
reverse(arr.begin(),arr.end());
for(string s:arr){
cout<<s<<" ";
}
return 0;
}

12、HJ34 图片整理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main(){
// 获取输入
string s;
getline(cin, s);
// 排序
sort(s.begin(), s.end());
cout <<s;
return 0;
}

13、HJ40 统计字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
using namespace std;

int main(){
// 获取输入
string s;
getline(cin, s);
// 排序
int a=0;
int A=0;
int space=0;
int num=0;
int other=0;
for(char c:s){
if(c>='A'&&c<='Z') A++;
else if(c>='a'&&c<='z') a++;
else if(c==' ') space++;
else if(c>='0'&&c<='9') num++;
else other++;
}
cout <<A+a<<endl;
cout <<space<<endl;
cout <<num<<endl;
cout <<other<<endl;
return 0;
}

14、HJ23 删除字符串中出现次数最少的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;

int main(){
// 获取输入
string s;
getline(cin,s);
// 统计频率
unordered_map<char, int> dict;
for(char c:s){
dict[c]++;
}
int min_q=20;
for(auto it:dict){
if(it.second<min_q) min_q=it.second;
}
// 从最后一个字符向前走
int left=0;
int right=0;
int n=s.length();
while(right<n){
if(dict[s[right]]==min_q){
right++;
}
else{
s[left++]=s[right++];
}
}
cout<<s.substr(0,left);
return 0;
}

15、HJ81 字符串字符匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main(){
// 获取输入
string s1;
string s2;
unordered_map<char,int> dict;
while(getline(cin, s1)){
getline(cin, s2);
bool flag=true;
for(char c:s2) dict[c]++;//统计长字符串中的所有字符频率
// 遍历短字符串
for(char c:s1){
// 如果有一个字符在字典中不存在则结果为false
if(dict.count(c)==0){
flag=false;
break;
}
}
if(flag) cout<<"true"<<endl;
else cout<<"false"<<endl;
}
}

16、 HJ56 完全数计算

完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。

它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。

例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
using namespace std;

int main(void){
int n;
cin>>n;
int count=0;
for(int i=6;i<=n;i++){
int temp=0;
for(int j=1;j<i;j++){//j<n,因为求和时不算这个数的自身
if(i%j==0)
temp+=j;
}
if(temp==i){
count++;
}
}
cout<<count<<endl;
return 0;
}

17、HJ99 自守数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
using namespace std;

int main(){
int n;
while(cin>>n){
int ans=0;
for(int i=1;i<=n;i++){
if(i%10==1||i%10==5||i%10==6){ //找到可能成为自守数的数
int temp1=i, temp2=i*i;
while(temp1){//验证后几位
if(temp2%10!=temp1%10) break;
temp1/=10;
temp2/=10;
}
if(temp1==0) ans++;//保证是满足条件才跳出的循环
}
}
cout<<ans+1<<endl;//带上0
}
return 0;
}

18、HJ6 质数因子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>
using namespace std;
int main()
{
long m;
while(cin>>m)
{
for(long i=2;i*i<=m;i++)
{
while(m%i==0)
{
cout<<i<<" ";
m/=i;
}
}
if(m>=2) cout<<m<<" ";//如果m=1,则while循环中刚好被质数分解完,如果大于1,说明没有被分解完,m就是那最后一个质数
//同时,这句也可以应对输入为质数的特殊情况
cout<<endl;
}
}

19 HJ60 查找组成一个偶数最接近的两个素数

质数(也叫素数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

查找组成偶数的最近两个素数

1.从偶数的一半开始查找;
2.判断两个数是否为素数;
3.如果是素数,则即为所求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;

bool isPrime(int n)
{
int i=0;
for(i=2;i*i<=n;i++)
{
if(n%i==0) return false;
}
return true;
}

int main()
{
int n;
while(cin>>n)
{
int left=n/2;
int right=n/2;
while(left>=2)
{
if(isPrime(left)&&isPrime(right))
{
cout<<left<<endl;
cout<<right<<endl;
break;
}
else
{
left--;
right++;
}
}
}
return 0;
}

20、 HJ94 记票统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

int main(void){
int n;
cin>>n;
string s;
vector<string>people;
unordered_map<string,int> mp;
for(int i=0;i<n;i++){
cin>>s;
people.push_back(s);
mp[s]=0;
}
int n2;
cin>>n2;
int Invalid=0;
for(int i=0;i<n2;i++){
cin>>s;
if(mp.count(s)!=0){
mp[s]++;
}
else{
Invalid++;
}
}
for(int i=0;i<n;i++){
cout<<people[i]<<" : "<<mp[people[i]]<<endl;
}
cout<<"Invalid"<<" : "<<Invalid<<endl;
return 0;
}