[TOC]

​ 华为机试题库共103道题目,其中入门级5道,简单级46道,中等级36道,较难级13道,困难级3道。计划在7天内共完成入门级,简单级,中等级的共计87道题目,则每天应当完成13道左右。计划每天完成:

​ 入门级:1道 简单级:7道 中等级:6道

一、基础数学篇(12)

1、HJ7 取近似值(入门)

#include<bits/stdc++.h>
using namespace std;

int main(){
    float n;
    cin>>n;
    int b=n;
    float c=n-b;
    if(c>=0.5){
        b+=1;
    }
    cout<<b;
    return 0;
}

2、HJ97 记负均正

#include<bits/stdc++.h>
using namespace std;
int main(){
    // 获取输入
    int n,tmp;
    cin>>n;
    int num_1=0;// 正数个数
    int num_2=0;// 负数个数
    double sum=0.0;
    while(n--){
        cin>>tmp;
        if(tmp>0) {
            sum+=tmp;
            num_1++;
        }
        else if(tmp<0)num_2++;
    }
    double mean=0.0;
    if(num_1!=0) mean=sum/num_1;
    printf("%d %.1f\n",num_2,mean);
    return 0;
}

3、HJ100 等差数列

#include<bits/stdc++.h>
using namespace std;

int getSum(int n,int& sum){
    int res=0;
    if(n==1) res=2;
    else res+=getSum(n-1,sum)+3;
    sum+=res;
    return res;
}

int main(){
    // 获取输入
    int n;
    cin>>n;
    // 递归调用
    int sum=0;
    getSum(n,sum);
    cout<<sum;
}

4、HJ72 百钱买百鸡问题

#include <bits/stdc++.h>
using namespace std;
/* 本题是一道解方程题,答案是唯一的,可以直接输出
但是为了
*/
int main(){
    int n;
    cout<<"0 25 75\n4 18 78\n8 11 81\n12 4 84"<<endl;  
//     for(int i=0;i<=100;i++)
//     {
//         for(int j=0;j<=100-i;j++)
//         {
//             if(5*i+j*3+(100-i-j)/3==100&&(100-i-j)%3==0)
//             {

//                 cout<<i<<" "<<j<<" "<<100-i-j<<endl;
//             }
//         }
//     }
    return 0;
}

5、HJ108 求最小公倍数

#include <bits/stdc++.h>
using namespace std;
/*求2个数的最小公倍数,其一定是2个数中最大数的整数倍
所以遍历的时候可以,最小是2个数中的最大值,最大是2个数的乘积,每次加一个最大数
*/
int main(){
    // 获取输入
    int n1,n2;
    cin>>n1>>n2;
    // 计算两个数的最小公倍数
    int max_v=n1*n2;
    int inin_v=max(n1,n2);// 最小的可能公倍数
    int res=inin_v;
    for(;res<=max_v;res+=inin_v){
        if(res%n1==0&&res%n2==0) break;
    }
    cout<<res;
}

6、HJ73 计算日期到天数转换

#include<bits/stdc++.h>
using namespace std;

int getDays(int y,int m){
    int days=0;
    // 二月份的天数
    if(m==2)
        // 如果是闰年,该年份能被 4 整除同时不能被 100 整除;或者该年份能被400整除。
        if((y%4==0&&y%100!=0)||y%400==0) days=29;
        // 如果不是闰年
        else days=28;
    // 天数为31的月份
    else if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)
        days=31;
    // 天数为30的月份
    else if(m==4||m==6||m==9||m==11)
        days=30;
    return days;
}

int main(){
    // 获取输入
    int y,m,d;
    cin>>y>>m>>d;
    // 处理字符串
    int res=0;
    for(int i=1;i<m;++i){
        res+=getDays(y,i);
    }
    res+=d;
    // 输出结果
    cout<<res<<endl;
    return 0;
}

7、HJ76 尼科彻斯定理

#include <bits/stdc++.h>
using namespace std;
/* 本题是求一个正整数m的m个连续奇数
这m个连续奇数正好是一个等差序列,假设第一个项是i,则第m项是i+*2(m-1)
则连续n个连续奇数和=(i+i+*2(m-1))*m/2=m*m*m
求得 i=m*m-m+1; 则输出得等差序列即可
*/
int main(){
    // 获取输入
    int m;
    cin>>m;
    int i=m*m-m+1;//m个连续奇数的第一个数
    // 输出m个连续奇数
    while(m--){
        if(m==0) cout<<i;//最后一个数后不需要"+"
        else cout<<i<<"+";
        i=i+2;//下一个奇数
    }
    return 0;
}

8、HJ53 杨辉三角的变形

#include<bits/stdc++.h>
using namespace std;
/*本题是一道杨辉三角的找规律题型:
只有n为1,2时,没有出现偶数,剩下的按照2 3 2 4的规律每四行循环一次。
n=1,index=-1
n=2,index=-1
n=3,index=2
n=4,index=3
n=5,index=2
n=6,index=4
n=7,index=2
n=8,index=3
n=9,index=4
n=10,index=2
*/
int main(){
    // 获取输入
    int n;
    cin>>n;
    // 处理
    if(n==1||n==2) cout<<-1<<endl;
    else if(n%4==3) cout<<2<<endl;
    else if(n%4==0) cout<<3<<endl;
    else if(n%4==1) cout<<2<<endl;
    else if(n%4==2) cout<<4<<endl;
    return 0;
}

9、HJ99 自守数

#include<bits/stdc++.h>
using namespace std;
/*
求自守数的解题思路
规律:个位数为 0、1、5、6 的数才可能是自守数,故采用筛选法,只判断符合该条件的数
思路1:可以把整数(数及其平方)转换为字符串,通过比较长字符串的末尾是否与短字符串相同即可
如:25 * 25 = 625,字符串'625'的末尾'25'与字符串'25'的相同
思路2:若该数的平方与该数的差,去模该数对应的各个进制位均等于零,则该数为自守数
如:25 * 25 = 625,625 - 25 = 600,600 % (10*1) = 0,600 % (10 * 2) = 0
*/
int main(){
    // 获取输入
    int n;
    cin>>n;
    // 递归调用
    int res=0;
    for(int i=0;i<=n;++i){
        //仅对个位数符合条件的数执行自守数的判断(没有该判断也能通过,加上效率更高)
        if((i%10 == 0) || (i%10 == 1) || (i%10 == 5) || (i%10 == 6)){
            long j = i*i;
            string s1=to_string(i);
            string s2=to_string(j);
            int n1=s1.length();
            int n2=s2.length();
            if(s2.substr(n2-n1,n1)==s1) res++;
        }
    }
    cout<<res;
}

10、HJ56 完全数计算

#include <bits/stdc++.h>
using namespace std;
/*求n以内的完全数,首先1肯定不是,所以遍历到n时应该从2开始
那么如果判断每个i是否是完全数呢?暴力搜索
遍历[2,i/2]中的数,计算除自身以外的约数和
*/
int main(){
    int n;  //待输入的数
    cin>>n;
    int count=0;  //计数器
    //遍历从2到n的每一个数,并在下一层for计算是否为完全数
    for(int i=2;i<=n;i++) 
    {
        int sum=1;  //每个数都包含1这个因数
        // 遍历[2,i/2]中的数,计算除自身以外的约数和
        for(int j=2;j<=i/2;j++) //除以2:根据题干推出的缩小i范围的方法
        {
            if(i%j==0)
                sum=sum+j;
        }
        // 如果约数和==i,说明是完全数
        if(i==sum) count++;
    }
    cout<<count<<endl;
    return 0;
}

11、HJ6 质数因子

#include <bits/stdc++.h>
using namespace std;
/*求一个正整数n的质数因子,首先1肯定不是,所以遍历到n时应该从2开始
正整数中质数有无穷多个。某个数的质因数是有限的,
而且除了最大的质因数,其他质因数的大小不会超过该数开方。
最坏的情况就是总共有两个质因数,每个质因数都是最大质因数,
那么该质因数就达到了上限:原数的开方。
所以解题思路为遍历2到该数开方的数,将原数依次相除,每个数都除到有余数为止;
那么其中非质因数的数相当于不会遍历到。直到最后剩下一个最大质因数或者1。
*/

int main(){
    // 获取输入
    int n;
    cin>>n;
    // n的质数因子的范围[2,sqrt(n)]
    for (int i = 2; i <= sqrt(n); ++i){
        // 如果n可以整除i,那么i就是一个质数因子
        while(n % i == 0){
            cout << i << ' ';
            n = n / i;// i
        }
    }
    if(n != 1)
        cout << n;
    return 0;
}

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

#include<bits/stdc++.h>
using namespace std;
// 判断一个数是否是素数/质数
bool is_prime(int n){
    // 质数:一个大于1的、除了1和自身都不能整除的自然数
    for(int i=2;i<n;i++){
        if(n%i==0) return false;
    }
    return true;
}

int main(){
    // 获取输入
    int n;
    cin>>n;
    // 遍历n的质数因子[2,sqrt(n)]
    int n1=0;
    int n2=0;
    int min_v=n;//最小的差值
    for(int i=sqrt(n);i<=n;i++){
        // 如果i<n-i并且i和n-i都是素数
        if(i<=n-i&&is_prime(i)&&is_prime(n-i)){
            int cur_min=n-i-i;
            if(cur_min<min_v){
                min_v=cur_min;
                n1=i;
                n2=n-i;
            }
        }
    }
    cout<<n1<<endl<<n2<<endl;
    return 0;
}

二、哈希篇(10)

1、HJ84 统计大写字母个数

#include <bits/stdc++.h>
using namespace std;

int main(){
    // 获取n个候选人的输入
    string s;
    getline(cin,s);
    // 输出大写字母的个数
    int res=0;
    for(char c:s){
        if(c>='A'&&c<='Z') res++;
    }
    cout<<res;
}

2、HJ10 字符个数统计

#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;
}

3、HJ40 统计字符

#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;
}

4、HJ9 提取不重复的整数(入门级)

#include<bits/stdc++.h>
using namespace std;

int main(){
    unordered_map<int,int> dict;// 统计频率
    int num;
    cin>>num;
    //从右向左扫描整数
    for(;0 < num;num /= 10){
        int cur=num%10;// 获取当前位的数字
        // 如果cur的数字为0说明之前没出现过
        if (!dict.count(cur)){
            dict[cur] = 1;//标记
            cout<<cur;
        }
    }
    return 0;
}

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

方法一:转换为小写后遍历

#include <iostream>
#include <string>
 
using namespace std;
int main(){
    // 获取输入
    string s;
    getline(cin, s);
    char c;
    cin>>c;
    // 计算结果
 	c=tolower(c);
    int res = 0;
    for (char i : s) {
        if (tolower(i) == c) {
            ++res;
        }
    }
    cout <<res;
}


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

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

int main()
{
    // 获取输入
    string s;
    getline(cin, s);
    char c;
    cin>>c;
    // 计算结果
 	c=tolower(c);
    unordered_map<char, size_t> dict;
    for (auto i : s) {
        ++dict[tolower(i)];
    }
    cout << dict[tolower(c)] << endl;
}

6、HJ81 字符串字符匹配

#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;
    }
}

7、HJ8 合并表记录

#include<iostream>
#include<string>
#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;
}

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

#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;
}

9、HJ94 记票统计

#include <bits/stdc++.h>
using namespace std;

int main(){
    // 获取n个候选人的输入
    int n;
    cin>>n;
    map<string,int> dict;// 字典,统计候选人票数
    vector<string> arr;// 数组,按照输入顺序保存,为了输出
    dict["Invalid"]=0;
    string tmp;
    while(n--){
       cin>>tmp;
       dict[tmp]=0;
       arr.push_back(tmp);
    }
    arr.push_back("Invalid");
    // 获取k个选票的输入
    int k;
    cin>>k;
    while(k--){
       cin>>tmp;
       if(dict.count(tmp))dict[tmp]++;// 有效选票
       else dict["Invalid"]++;// 无效选票
    }
    // 输出结果
    for(auto s:arr) cout<<s<<" : "<<dict[s]<<endl;
}

10、HJ102 字符统计

#include <bits/stdc++.h>
using namespace std;

class mycomp{
public:
    bool operator()(const pair<char,int>& a,const pair<char,int>& b){
        if(a.second==b.second){
            return a.first>b.first;
        }
        else{
            return a.second<b.second;
        }
    }
};

int main(){
    // 获取输入
    string s;
    unordered_map<char,int> dict;
    priority_queue<pair<char,int>,vector<pair<char,int>>,mycomp> que;
    while(getline(cin, s)){
        for(char c:s) dict[c]++;//统计长字符串中的所有字符频率
        // 遍历短字符串
        for(auto p:dict){
            que.push(p);
        }
        // 输出
        while(!que.empty()){
            auto p=que.top();
            que.pop();
            cout<<p.first;
        }
        cout<<endl;
    }
}

三、数组篇(8 )

1、HJ11 数字颠倒

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
    int n;
    cin>>n;
    string s=to_string(n);// 转换为数字
    reverse(s.begin(),s.end());
    cout<<s<<endl;
    return 0;
}

2、HJ58 输入n个整数,输出其中最小的k个

#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;
}

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

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
bool cmp(int a,int b){
    return a>b;
}

int main(){
    // 获取输入
    int n;
    cin>>n;
    int temp;
    vector<int> arr;
    while(n--){
        cin>>temp;
        arr.push_back(temp);
    }
    int k;
    cin>>k;
    // 返回结果
    if(k==0){
        sort(arr.begin(),arr.end());
    }
    else if(k==1){
        sort(arr.begin(),arr.end(),cmp);
    }
    // 输出结果
    for(int i=0;i<arr.size();++i){
         cout<<arr[i]<<" ";
    }
    return 0;
}

4、HJ15 求int型正整数在内存中存储时1的个数

#include <bits/stdc++.h>
using namespace std;
int main(){
    // 获取输入
    int n;
    cin>>n;
    int res=0;
    while(n){
        if(n%2==1) res++;
        n=n/2;
    }
    cout<<res;
}

5、HJ62 查找输入整数二进制中1的个数

#include<bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    int n;
    while(cin>>n){
        int res=0;
        while(n){
            if(n%2==1) res++;
            n=n/2;
        }
        cout<<res<<endl;
    }
    return 0;
}

6、HJ86 求最大连续bit数

#include <bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    int n;
    cin>>n;
    //转换为二进制
    string s;// 该数字的二进制格式
    while(n){
        s=to_string(n%2)+s;
        n=n/2;
    }
    // 记录该二进制下的连续1的个数
    int res=0;
    for(int i=0;i<s.length();++i){
        // 从i出发,计算连续1的个数tmp
        int tmp =0;    //计数器,存放临时变量
        while(i<s.length()&&s[i]=='1'){
            tmp++;
            i++;
        }
        // 保存历史最大值
        res=max(res,tmp);
    }
    cout<<res;
}

7、HJ5 进制转换

#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;
}

8、HJ80 整型数组合并

#include<bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    int n1,n2,tmp;
    vector<int> s1;
    vector<int> s2;
    cin>>n1;
    while(n1--){
        cin>>tmp;
        s1.push_back(tmp);
    }
    cin>>n2;
    while(n2--){
        cin>>tmp;
        s2.push_back(tmp);
    }
    // 将2个数组排序下
    sort(s1.begin(), s1.end());
    sort(s2.begin(), s2.end());
    // 同时合并两个有序数组
    string res;
    int i=0;
    int j=0;
    unordered_set<int> set;//哈希集合,用来去重
    while(i<s1.size()&&j<s2.size()){
        // 谁小添加谁
        if(s1[i]<=s2[j]) {
            // 如果之前集合中没有才添加,保证不会有重复的
            if(!set.count(s1[i])){
                set.insert(s1[i]);
                res+=to_string(s1[i]);
            }
            i++;
        }
        else if(s1[i]>s2[j]){
            // 如果之前集合中没有才添加,保证不会有重复的
            if(!set.count(s2[j])){
                set.insert(s2[j]);
                res+=to_string(s2[j]);
            }
            j++;
        }
        
    }
    while(i<s1.size()){
        // 如果之前集合中没有才添加,保证不会有重复的
        if(!set.count(s1[i])){
                set.insert(s1[i]);
            res+=to_string(s1[i]);
        }
        i++;
    }
    while(j<s2.size()){
        // 如果之前集合中没有才添加,保证不会有重复的
        if(!set.count(s2[j])){
            set.insert(s2[j]);
            res+=to_string(s2[j]);
        }
        j++;
    }
    cout<<res<<endl;
    return 0;
}

四、字符串篇(13)

1、HJ46 截取字符串

#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;
}

2、HJ34 图片整理

#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;
}

3、HJ14 字符串排序

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


int main(){
    // 获取输入
    string s;
    int k;
    cin>>k;
    vector<string> arr;
    while(k--){
        cin>>s;
        arr.push_back(s);
    }
    sort(arr.begin(),arr.end());
    for(int i=0;i<arr.size();i++){
        cout<<arr[i]<<endl;
    }
    return 0;
}

4、HJ12 字符串反转

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

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

5、HJ106 字符逆序

#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;
}

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

#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;
}

7、HJ4 字符串分隔

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

int main(){
    // 获取输入
    string str;
    while(cin >> str){
        int len = str.size();
        // 如果字符串不是8的倍数,在字符串后添加count个'0'
        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;
}

8、HJ21 简单密码

#include<bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    string s;
    getline(cin,s);
    // 处理字符串
    vector<pair<string,int>> arr;
    for(int i=0;i<s.length();++i){
        if(s[i]>='A'&&s[i]<='Z'){
            if(s[i]=='Z') s[i]='a';
            else {
                s[i]=tolower(s[i]+1);
            }
        }
        else if(s[i]>='a'&&s[i]<='c'){
            s[i]='2';
        }
        else if(s[i]>='d'&&s[i]<='f'){
            s[i]='3';
        }
        else if(s[i]>='g'&&s[i]<='i'){
            s[i]='4';
        }
        else if(s[i]>='j'&&s[i]<='l'){
            s[i]='5';
        }
        else if(s[i]>='m'&&s[i]<='o'){
            s[i]='6';
        }
        else if(s[i]>='p'&&s[i]<='s'){
            s[i]='7';
        }
        else if(s[i]>='t'&&s[i]<='v'){
            s[i]='8';
        }
        else if(s[i]>='w'&&s[i]<='z'){
            s[i]='9';
        }
    }
    cout<<s<<endl;
    return 0;
}

9、HJ13 句子逆序

#include <iostream>
#include <string>
#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;
    }
}

10、HJ31 单词倒排

#include <iostream>
#include <string>
#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--]);
}

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 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;
    }
}
// 将所有的非字母字符替换为空格
void update(string &str){
    for(int i=0;i<str.size();i++){
        if(!is_A(str[i])&&!is_a(str[i])) str[i]=' ';
    }
}
int main(){
    // 获取输入
    string s;
    while(getline(cin, s)){
        update(s);
        split(s);
        reverse(s.begin(), s.end());
        cout <<s;
    }
    return 0;
}

11、HJ85 最长回文子串

#include<bits/stdc++.h>
#include<cmath>
using namespace std;
// 判断是否是回文子串
bool is_true(string & s){
    int left=0;
    int right=s.length()-1;
    while(left<=right){
        if(s[left++]!=s[right--]) return false; 
    }
    return true; 
}

int main(){
    // 获取输入
    string s;
    getline(cin, s);
    //定义动态数组
    int len=s.length();
    int res=0;
    for(int i=0;i<len;i++){
        for(int j=1;j<len-i+1;j++){
            string str=s.substr(i,j);
            //cout<<str<<endl;
            if(is_true(str)&&res<str.length()) res=str.length();
        }
    }
    cout<<res<<endl;
    return 0;
}

12、HJ87 密码强度等级

#include<bits/stdc++.h>
using namespace std;
int main(){
    // 获取输入
    string s;
    getline(cin,s);
    // 计算分数
    int score=0;
    // 检查长度
    int len=s.length();
    if(len<=4) score+=5;
    else if(len<=7) score+=10;
    else if(len>=8) score+=25;
    // 统计字母、数字、符号的个数
    int alpha_A=0;
    int alpha_a=0;
    int digit=0;
    int other=0;
    for(char c:s){
        if(isdigit(c))digit++;
        else if(c>='a'&&c<='z')alpha_a++;
        else if(c>='A'&&c<='Z')alpha_A++;
        else other++;
    }
    //cout<<alpha_A<<alpha_a<<digit<<other;
    //检查字母
    if(alpha_A==0&&alpha_a==0) score+=0;
    else if(alpha_A==0||alpha_a==0) score+=10;
    else if(alpha_A>0||alpha_a>0)score+=20;
    //cout<<score;
    // 检查数字
    if(digit==0) score+=0;
    else if(digit==1) score+=10;
    else if(digit>1)score+=20;
    //cout<<score;
    // 检查符号
    if(other==0) score+=0;
    else if(other==1) score+=10;
    else if(other>1)score+=25;
    //cout<<score;
    // 检查奖励
    int n=0;
    if((alpha_a>0||alpha_A>0)&&digit>0) n=3;
    if((alpha_a>0||alpha_A>0)&&digit>0&&other>0) n=3;
    if(alpha_a>0&&alpha_A>0&&digit>0&&other>0)n=5;
    score+=n;
    //cout<<score;
    // 输出结果
    if(score>=90) cout<<"VERY_SECURE"<<endl;
    else if(score>=80) cout<<"SECURE"<<endl;
    else if(score>=70) cout<<"VERY_STRONG"<<endl;
    else if(score>=60) cout<<"STRONG"<<endl;
    else if(score>=50) cout<<"AVERAGE"<<endl;
    else if(score>=25) cout<<"WEAK"<<endl;
    else if(score>=0) cout<<"VERY_WEAK"<<endl;
    return 0;
}

13、HJ96 表示数字

#include<bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    string s;
    cin>>s;
    // 处理字符串
    for(int i = 0; i < s.length(); i++){
        if(isdigit(s[i])){ // 每次第一个遇到的数字前加*
            s.insert(i, "*");
            i++;
            while(isdigit(s[i])) //遍历连续的数字找到这一段的最后一个数字
                i++;
            s.insert(i, "*"); //最后加*
        }
    }
    // 输出结果
    cout << s << endl;
    return 0;
}

五、链表篇(1)

1、HJ51 输出单向链表中倒数第k个结点

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

struct ListNode
{
    int m_nKey;
    ListNode* m_pNext;
    ListNode(int val){m_nKey=val;m_pNext=nullptr;}
};


int main(){
    // 获取输入
    int n;
    ListNode* myCode= new ListNode(0);
    while(cin>>n){
        int tmp=0;
        ListNode* p=myCode;// 非常重要,遍历指针法
        while(n--){
            cin>>tmp;
            //创建单链表
            ListNode* newCode= new ListNode(tmp);
            p->m_pNext=newCode;
            p=p->m_pNext;
        }
        // 获取k
        cin>>tmp;
        ListNode* left=myCode->m_pNext;
        ListNode* right=myCode->m_pNext;
        while(tmp--) {
            right=right->m_pNext;
        }
        while(right){
            left=left->m_pNext;
            right=right->m_pNext;
        }
        cout<<left->m_nKey<<endl;
    }
}

六、递归篇(2)

1、HJ37 统计每个月兔子的总数

#include <bits/stdc++.h>
using namespace std;
/*斐波那契数列:1:1 2:1 3:2 4:3 5:5 6:8*/
int getSum(int n) { //求每个月兔子数
    if(n == 1 || n == 2) //n=1或2跳出递归
        return 1;
    return getSum(n - 1) + getSum(n - 2); //返回前两个月相加
}
int main(){
    // 获取输入
    int n;
    cin>>n;
    // 输出结果
    int res;
    res=getSum(n);
    cout<<res;
}

2、HJ61 放苹果

#include<bits/stdc++.h>
using namespace std;

// 把m个苹果放在n个盘子里的分法
int f(int m,int n){
    // 如果只有1个盘子或者苹果数为0,则只有一种分法
    if(m==0 || n==1)
        return 1;
    // 如果n>m,则必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) f(m,n) = f(m,m)  
    else if(n>m)
        return f(m,m);
    // 如果n<=m,则盘子数比苹果数少
    else
        /* 存在如下2种情况:
        1、有至少一个盘子空着,则可以拿走这个盘子,即相当于f(m,n) = f(m,n-1);
        2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
        而总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
        */
        return f(m,n-1)+f(m-n,n);// 把m个苹果放在n-1个盘子里的分法
}

int main(){
    // 获取输入
    int m,n;
    cin>>m>>n;
    // 输出结果
    cout << f(m,n) << endl;
}

七、模拟篇(3)

1、HJ35 蛇形矩阵

#include <bits/stdc++.h>
using namespace std;

int main(){
    // 获取输入
    int n;
    cin>>n;
    // 间隔变,计算各个数字
    int beg=1;// 每行的开始数字
    for(int i=1;i<=n;i++)
    {
        cout<<beg;
        int tmp = beg;// 每行中的数
        for(int j=i+1;j<=n;j++)
        {
            tmp+=j;
            cout<<" "<<tmp;              
        }
        cout<<endl;
        beg+=i;
    }
}

2、HJ83 二维数组操作

#include<bits/stdc++.h>
using namespace std;
/*这道题不需要实现表格功能,只要满足对应的输入输出即可*/
int main(){
    int m,n;    //数据表的行数和列数
    while(cin>>m>>n) {    //输入数据表的行数和列数
        // 初始化表格
        if(m>9 || n>9)    //如果行数或者列数大于9,返回-1,否则返回0
            cout<<-1<<endl;
        else
            cout<<0<<endl;
        // 交换2个坐标
        int x1,y1,x2,y2;    //(x1,y1)(x2,y2)为两个坐标
        cin>>x1>>y1>>x2>>y2;    //分别输入x1,y1,x2,y2的值
        if(x1>=m || y1>=n || x2>=m || y2>=n)    //如果行坐标的值大于等于数据表的行数;或者列坐标的值大于等于数据表的列数,那么返回-1,否则返回0
            cout<<-1<<endl;
        else
            cout<<0<<endl;
        // 在row上添加一行
        int row;    //row为行号
        cin>>row;    //输入行号
        if(row<0 && row>=m || m==9)    //如果行号大于数据表的行数,或者数据表的行数为9,则返回-1,否则返回0
            cout<<-1<<endl;
        else
            cout<<0<<endl;
        // 在column左边添加一列
        int column;    //row为列号
        cin>>column;    //输入列号
        if(column<0 || column>=n || n==9)    //如果列号大于数据表的列数,或者数据表的列数为9,则返回-1,否则返回0
            cout<<-1<<endl;
        else
            cout<<0<<endl;
        // 查询x和y的坐标值
        int x,y;    //(x,y)为坐标
        cin>>x>>y;    //输入x和y的值
        if(x<0 || x>=m || y<0 || y>=n)    //如果行坐标的值大于等于数据表的行数;或者列坐标的值大于等于数据表的列数,那么返回-1,否则返回0
            cout<<-1<<endl;
        else
            cout<<0<<endl;
    }
    return 0;
}

3、HJ22 汽水瓶

#include<bits/stdc++.h>
using namespace std;
/*
方法一:观察规律
注意到每两个空汽水瓶就可以通过借一个空汽水瓶来喝到一瓶汽水,
故最多可以喝到的汽水瓶数等于空汽水瓶数除以二,即 sum = num / 2
方法二:
n>=2时才有可能喝到汽水,只要手上的空汽水瓶数大于或等于2,不论情况如何,先借一个空汽水瓶
*/
int main(){
    int num;
    while(cin>>num){
        if(num==0) break;// 0表示输入结束,不用处理
        int sum = 0; //计数器,最多可以喝的汽水瓶数
        // 空汽水瓶数大于或等于 2 时,至少可以喝到一瓶汽水,如通过“先借后还”方式就可以喝到汽水
        while (num >= 2)
        {
            num += 1; //只要手上的空汽水瓶数大于或等于2,不论情况如何,先借一个空汽水瓶
            int count = num / 3; //一次空汽水瓶换汽水操作后可以喝到的汽水瓶数(3 个空汽水瓶换 1 瓶汽水,喝它!)
            num = num % 3 + count - 1; //剩下的空汽水瓶数,包括之前没换的空汽水瓶 + 喝完汽水后的空汽水瓶 + 要还回去空汽水瓶(之前借了一个空汽水瓶);
            sum += count; //累计可以喝到的汽水瓶数
        }
        cout<<sum<<endl;
    }
    return 0;
}

八、动态规划篇(1)

1、HJ91 走方格的方案数

(1)递归法

#include<bits/stdc++.h>
using namespace std;

// f(n,m)表示从[0,0]到[n-1,m-1]的走法数
int f(int n,int m){
    if(n==0||m==0) return 1;// 当处于第一列或第一行时,明显只有一种走法
    return f(n-1,m)+f(n,m-1);
}

int main(){
    // 获取输入
    int n,m;
    cin>>n>>m;
    cout<<f(n,m)<<endl;
    return 0;
}

(2)动态规划法

#include<bits/stdc++.h>
using namespace std;
/* 解析:本类型题是网格路径问题,可以看做是二维版本的爬楼梯问题
    【状态定义】:dp[i][j] 表示的含义为从[0,0]到[i-1,j-1]的走法数
    【转移方程】:[i,j]只能是从上一格[i,j-1]或者左一格[i-1,j]达到
    所以dp[i][j]=dp[i][j-1]+dp[i-1][j];
    */
int main(){
    // 获取输入
    int n,m;
    cin>>n>>m;
    //定义动态数组
    vector<vector<int>> dp(n + 1,vector<int>(m + 1,0)) ;
    for(int i=0;i<=n;i++) dp[i][0]=1;
    for(int i=0;i<=m;i++) dp[0][i]=1;
    // 遍历[1,1]到[n,m]
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            dp[i][j] =dp[i-1][j]+dp[i][j - 1];
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}

九、栈篇(1)

1、HJ54 表达式求值

#include<iostream>
#include<stack>
using namespace std;
 
void compute(stack<int>& st1, stack<char>& st2){ //根据栈顶运算符弹出栈顶两个元素进行运算
    int b = st1.top();
        st1.pop();
    int a = st1.top();
        st1.pop();
    char op = st2.top(); //栈顶运算符
        st2.pop();
    if(op == '+') a = a + b; //加
    else if(op == '-') a = a - b; //减
    else if(op == '*') a = a * b; //乘
    else if(op == '/') a = a / b; //除
    st1.push(a);
}
 
bool priority(char m, char n){ //比较运算符优先级
    if(m == '(') //括号优先级最高
        return false;
    else if((m == '+' || m == '-') && (n == '*' || n == '/')) //加减法小于乘除法
        return false;
    return true;
}
int main(){
    string s;
    while(cin >> s){
       stack<int> st1; //记录运算数字
       stack<char> st2; //记录运算符
       st2.push('('); //整个运算式添加括号
       s += ')';
       bool flag = false;
       for(int i = 0; i < s.length(); i++){
           if(s[i] == '(') //如果是左括号都在运算符栈加入(
               st2.push('(');
           else if(s[i] == ')'){ //遇到右括号
               while(st2.top() != '('){ //弹出开始计算直到遇到左括号
                   compute(st1, st2);
               }
               st2.pop(); //弹出左括号
           } else if(flag){ //运算符
               while(priority(st2.top(), s[i])){ //比较运算优先级
                   compute(st1, st2); //可以直接计算
               }
               st2.push(s[i]); //需要将现阶段加入栈中等待运算
               flag = false;
           } else{ //数字
                int j = i; //记录起始
                if(s[j] == '-' || s[j] == '+') //正负号
                    i++;
                while(isdigit(s[i])){
                    i++;
                }
                string temp = s.substr(j, i - j);
                st1.push(stoi(temp)); //截取数字部分,转数字
                i--;
                flag = true; //数字结束,下一次flag为true就是运算符了
           }
       }
      cout << st1.top() << endl; //输出
    }
    return 0;
}